您的位置:首页 > 其它

MFC中消息循环机制

2015-09-01 12:38 225 查看
在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消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗口,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: