Windows下,每个线程都可以拥有一个消息队列,通常UI线程默认就拥有自己的消息队列,Work Thread需要自己调用PeekMessage来创建自己的消息队列。
消息是一个数据结构,下面是它的定义:
typedef
struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
#ifdef
_MAC
DWORD lPrivate;
#endif
} MSG
每个消息都包含了要接收消息的窗口的句柄,消息ID,两个参数,还有其他信息。SDK下的消息循环通常这样写:
while
(GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
除非GetMessage函数从消息队列中获取到了WM_QUIT消息,否则这个循环将永远进行下去。循环内部先对加速键和键盘消息进行处理,然后发送该消息到指定窗口,因为消息本身包含了窗口的句柄,所以目的地不用再明确指定。
当目标窗口接收到消息后,窗口过程函数就会被执行,根据不同的消息进行相应的处理。
因为窗口过程函数和窗口类名在注册窗口的时候建立了对应关系。创建窗口时,我们又使用了窗口类名,所以可以推测创建成功后获得的窗口句柄和窗口过程函建立了映射。
下面是一个典型的窗口过程函数:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}