在MFC中通过重载CWnd类中的虚拟函数PreTranslateMessage,可以改变消息控制流程。
只有经过消息队列的消息才受PreTranslateMessage的影响,使用SendMessage函数发送或其他类似方式直接向窗口发送消息是不经过消息队列的。
在消息处理函数中,不能处理WM_CHAR消息。
SetWindowText会发送WM_CHAR字符消息。
GetMessage在没有消息的时候等待消息,cpu占用率当然低。
PeekMessage没有消息的时候立刻返回,可以在没有消息的时候可以做其他处理,但cpu占用率一般较高。
因为游戏不能靠windows消息驱动,所以要用PeekMessage();
MFC通过CWinApp类中的Pumpmessage函数实现消息循环,但是实际的消息循环代码位于CWinThread中,CWinApp只是从CWinThread继承过来。
流程图:
其简化后的代码大概如下:
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消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗口,