WTL的消息机制

    技术2022-05-11  73

    WTL的消息机制

    高歌

     

    一、SDI流程

    Run全局线程

          1、 Module.AddMessageLoop(&theLoop), 保存CMessageLoop与一个线程id的对应,Module是全局变量。

          2、 wndMain的构造,初始化变量

          3、  wndMainCreateEx

                  wndMainCreate

                         注册窗口类(窗口过程的地址是StartWindowProc)

                         调用基类CframeWindowImplBaseCreate

                                       保存实例的this_module_Module.AddCreateWndData(&m_thunk.cd, this);

     Win32CreateWindow函数

    CreateWindow将触发第一个WM_XXX消息,从而调用StartWindowProc

    StartWindowProc主要是初始化一个thunk代码,并将窗口过程修改为thunk的开始处,thunk代码先将堆栈中保存HWND的位值中放入this指针,然后用jmp跳到WndProc函数进行处理

           4、调用wndMain.ShowWindow(nCmdShow);

       5、int nRet = theLoop.Run();

       6、_Module.RemoveMessageLoop();

    线程结束

     

    二、消息循环

    // theLoop.Run();

             int Run()

             {

                      BOOL bDoIdle = TRUE;

                      int nIdleCount = 0;

                      BOOL bRet;

                      for(;;)

                      {

                               //检测队列中有无消息

    while(!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE) && bDoIdle)

                              {

                                       if(!OnIdle(nIdleCount++))

                                                bDoIdle = FALSE;

                              }

                              //得到消息并从队列中去除

                               bRet = ::GetMessage(&m_msg, NULL, 0, 0);

                               if(bRet == -1)

                              {

                                       ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)/n"));

                                       continue;  // error, don't process

                              }

                               //bRet0表示收到WM_QUIT

                               else if(!bRet)

                              {

                                       ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting/n"));

                                       break;                // WM_QUIT, exit message loop

                              }

     

                               //PreTranslateMessage遍历CMessageFilter如果有一个则调用并返回TRUE

                              //如果在窗口类中定义这个函数并且加入了filter他将不被发到窗口过程中去。

                              //注意这个函数是虚函数

                               if(!PreTranslateMessage(&m_msg))

                              {

                                       ::TranslateMessage(&m_msg);

                                       ::DispatchMessage(&m_msg);

                              }

                               if(IsIdleMessage(&m_msg))

                              {

                                       bDoIdle = TRUE;

                                       nIdleCount = 0;

                              }

                      }

                      return (int)m_msg.wParam;

             }

     

    三、ProcessMessage

    ProcessMessage是一个虚函数,由派生类中通过宏定义实现被

    WndProc调用。

     

     

    参考文章

    http://www.rpi.edu/~pudeyo/articles/wndproc/

     


    最新回复(0)