Reputation: 6390
This is a very simple code using the Windows API, where a child window is painted in the central part of the app window. By clicking with the mouse left button on the main window client area, the child window assumes a null height. By clicking with the mouse right button, the child window has its height increased by 10 pixels, at each mouse click. One can hear a beep every time a left, or right mouse click occurs in the window's app, due to the MessageBeep(-1)
call made while painting the parent window.
The curious thing is that when you drag one of the sides of the parent window, changing its width or height, very slowly, you can hear the beeps, at each move. But if you drag the window's side a little bit faster, you'll hear just one beep, many many seconds after the mouse button was released. Why is that?
This is the code:
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND, UINT, UINT, LONG);
LRESULT CALLBACK ChildProc(HWND, UINT, UINT, LONG);
/****************************************************************************************************************************
WinMain()
****************************************************************************************************************************/
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASSEX wndclassx;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = 0;
wndclassx.lpfnWndProc = WindowProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclassx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclassx.lpszMenuName = NULL;
wndclassx.lpszClassName = L"ParentWindow";
wndclassx.hIconSm = NULL;
if( !RegisterClassEx(&wndclassx) ) return 0;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = 0;
wndclassx.lpfnWndProc = ChildProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = 0;
wndclassx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclassx.lpszMenuName = NULL;
wndclassx.lpszClassName = L"ChildWindow";
wndclassx.hIconSm = NULL;
if( !RegisterClassEx(&wndclassx) ) return 0;
HWND hWnd;
if( !(hWnd = CreateWindow(L"ParentWindow", L"Parent Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL)) ) return 0;
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
/****************************************************************************************************************************
WindowProc()
****************************************************************************************************************************/
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
PAINTSTRUCT ps;
switch ( message )
{
RECT rect;
HWND hChild;
case WM_CREATE:
GetClientRect(hwnd, &rect);
if( !CreateWindow(L"ChildWindow", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, rect.right / 3, rect.bottom / 3, rect.right / 3,
rect.bottom / 3, hwnd, (HMENU)0, ((LPCREATESTRUCT)lParam)->hInstance, NULL) ) return -1;
break;
case WM_SIZE:
MoveWindow(GetDlgItem(hwnd, 0), LOWORD(lParam) / 3, HIWORD(lParam) / 3, LOWORD(lParam) / 3, HIWORD(lParam) / 3,
true);
break;
case WM_LBUTTONDOWN:
hChild = GetDlgItem(hwnd, 0);
GetWindowRect(hChild, &rect);
ScreenToClient(hwnd, (LPPOINT)&rect);
ScreenToClient(hwnd, (LPPOINT)&rect.right);
MoveWindow(hChild, rect.left, rect.top, rect.right - rect.left, 0, true);
break;
case WM_RBUTTONDOWN:
hChild = GetDlgItem(hwnd, 0);
GetWindowRect(hChild, &rect);
ScreenToClient(hwnd, (LPPOINT)&rect);
ScreenToClient(hwnd, (LPPOINT)&rect.right);
MoveWindow(hChild, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 10, true);
break;
case WM_PAINT:
BeginPaint(hwnd, &ps);
MessageBeep(-1);
EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
/****************************************************************************************************************************
ChildProc()
****************************************************************************************************************************/
LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
switch( message )
{
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
Upvotes: 0
Views: 80
Reputation: 54584
To quote from this KB article on MSDN:
With normal use of
GetMessage()
(passing zeros for all arguments except theLPMSG
parameter) orPeekMessage()
, any message on the application queue is processed before user input messages. And input messages are processed beforeWM_TIMER
andWM_PAINT
"messages."
In other words, because you call MessageBeep
during WM_PAINT
, it won't happen until after the window stops processing user input, e.g., when the user stops moving the window around.
Upvotes: 1