阳光VIP

少壮不努力,老大徒伤悲。平日弗用功,自到临期悔。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SDK消息循环机制

Posted on 2012-02-04 21:53  阳光VIP  阅读(187)  评论(0编辑  收藏  举报

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;
}