MFC中消息循环机制

在MFC中通过重载CWnd类中的虚拟函数PreTranslateMessage,可以改变消息控制流程。

只有经过消息队列的消息才受PreTranslateMessage的影响,使用SendMessage函数发送或其他类似方式直接向窗口发送消息是不经过消息队列的。

在消息处理函数中,不能处理WM_CHAR消息。

SetWindowText会发送WM_CHAR字符消息。

GetMessage在没有消息的时候等待消息,cpu占用率当然低。

PeekMessage没有消息的时候立刻返回,可以在没有消息的时候可以做其他处理,cpu占用率一般较高。

因为游戏不能靠windows消息驱动,所以要用PeekMessage();

MFC通过CWinApp类中的Pumpmessage函数实现消息循环,但是实际的消息循环代码位于CWinThread中,CWinApp只是从CWinThread继承过来

流程图:

MFC中消息循环机制_第1张图片

其简化后的代码大概如下:

BOOL CWinThread::PumpMessage()

{

         ASSERT_VALID(this);

 

         if(!::GetMessage(&m_msgCur, NULL, NULL, NULL))

         {

#ifdef _DEBUG

                   if(afxTraceFlags & traceAppMsg)

                            TRACE0("CWinThread::PumpMessage- Received WM_QUIT.\n");

                   m_nDisablePumpCount++;// application must die

                            //Note: prevents calling message loop things in 'ExitInstance'

                            // will never be decremented

#endif

                   returnFALSE;

         }

 

#ifdef _DEBUG

         if(m_nDisablePumpCount != 0)

         {

                   TRACE0("Error:CWinThread::PumpMessage called when not permitted.\n");

                   ASSERT(FALSE);

         }

#endif

 

#ifdef _DEBUG

         if(afxTraceFlags & traceAppMsg)

                  _AfxTraceMsg(_T("PumpMessage"),&m_msgCur);

#endif

 

         //process this message

 

         if(m_msgCur.message != WM_KICKIDLE &&!PreTranslateMessage(&m_msgCur))

         {

                   ::TranslateMessage(&m_msgCur);

                   ::DispatchMessage(&m_msgCur);

         }

         returnTRUE;

}


BOOL CWinThread::PreTranslateMessage(MSG*pMsg)

{

         ASSERT_VALID(this);

 

         //if this is a thread-message, short-circuit this function

         if(pMsg->hwnd == NULL && DispatchThreadMessageEx(pMsg))

                   returnTRUE;

 

         //walk from target to main window

         CWnd*pMainWnd = AfxGetMainWnd();

         if(CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))

                   returnTRUE;

 

         //in case of modeless dialogs, last chance route through main

         //   window's accelerator table

         if(pMainWnd != NULL)

         {

                    CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);

                    if (pWnd->GetTopLevelParent() != pMainWnd)

                            returnpMainWnd->PreTranslateMessage(pMsg);

         }

 

         returnFALSE;   // no special processing

}


BOOL CWinThread::PreTranslateMessage(MSG*pMsg)

{

         ASSERT_VALID(this);

 

         //if this is a thread-message, short-circuit this function

         if(pMsg->hwnd == NULL && DispatchThreadMessageEx(pMsg))

                   returnTRUE;

 

         //walk from target to main window

         CWnd*pMainWnd = AfxGetMainWnd();

         if(CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))

                   returnTRUE;

 

         //in case of modeless dialogs, last chance route through main

         //   window's accelerator table

         if(pMainWnd != NULL)

         {

                    CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);

                    if (pWnd->GetTopLevelParent() != pMainWnd)

                            returnpMainWnd->PreTranslateMessage(pMsg);

         }

 

         returnFALSE;   // no special processing

}


BOOL CWnd::PreTranslateMessage(MSG* pMsg)

{

         //handle tooltip messages (some messages cancel, some may cause it to popup)

         AFX_MODULE_STATE*pModuleState = _AFX_CMDTARGET_GETSTATE();

         if(pModuleState->m_pfnFilterToolTipMessage != NULL)

                   (*pModuleState->m_pfnFilterToolTipMessage)(pMsg,this);

 

         //no default processing

         returnFALSE;

}

windows消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗口,



你可能感兴趣的:(VC++)