消息产生:消息由系统或程序产生,并不断加入到消息队列中。
消息获取:程序启动后执行到theApp的Run函数,死循环不断的取消息,再推送消息CWinThread::PumpMessage()(调用) ->::DispatchMessage(&m_msgCur)(图示)->AfxWndProc(调用)->CWnd::WindowProc(调用)->OnWndMsg()->根据消息类型执行OnCommand、OnNotify或者查询消息映射表向基类上溯。
在窗口产生时注册了消息处理回调
消息映射表:消息映射表的组建采用与RTTI类似的方式使用宏DECLARE_MESSAGE_MAP、BEGIN_MESSAGE_MAP、END_MESSAGE_MAP,三个宏定义每种类型保存一个AFX_MSGMAP的static对象一个直线自己的AFX_MSGMAP_ENTRY消息处理列表(数组),一个直线父类的消息处理列表(用于上溯)。在BEGIN_MESSAGE_MAP、END_MESSAGE_MAP之间给列表项赋值。许多标准消息使用宏在AFXMSG_.H文件中定义。
拐弯上溯:在上述消息过去的过程中OnWndMsg()会根据消息类型分别执行OnCommand或OnNotify。以OnCommand为例,根据多态性最终将执行到CFrameWnd::OnCmdMsg函数:
BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo)
{
// pump through current view FIRST
CView* pView = GetActiveView();
if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
// then pump through frame
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
// last but not least, pump through app
CWinApp* pApp = AfxGetApp();
if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
return FALSE;
}
先在CView中上溯查找,查之不得调用m_pDocument->OnCmdMsg上溯查找,又查之不得交由m_pDocTemplate->OnCmdMsg,都无法查找得到继续执行CWnd::OnCmdMsg函数查询CCmdTarget消息映射表,最后还是无法得到则交由CWinApp处理。查询循序如下图:
知道消息被处理为止。
AfxSig_xx说明:用于表示消息处理类型有多少参数。保证回调函数的调用过程安全。