读书人

深入显出MFC笔记(3)

发布时间: 2012-11-23 22:54:33 作者: rapoo

深入浅出MFC笔记(3)

深入显出MFC笔记(3)

深入显出MFC笔记(3)


MFC六大关键技术之六消息的绕行:command routing (消息的二万五千里长征)

LRESULT AfxWndProc (HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam,CWnd *pWnd)

{//推动引擎的起始点。在CWinThread:: Run 中被调用

return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);

}

LRESULT AfxCallWndProc(CWnd* pWnd,,HWND hWnd, UINT nMsg,WPARAM wParam, LPARAM lParam)

{

LRESULT lResult = pWnd->WindowProc(nMsg, wParam, lParam);

return lResult;

} //pWnd-> Window是虚拟函数,调用pWnd指向对象的函数,但子类没有改写其实是CWnd:: WindowProc

LRESULT CWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam){

AFX_MSGMAP* pMessageMap;

AFX_MSGMAP_ENTRY* lpEntry;

if (nMsg == WM_COMMAND) { // 判断消息是否为WM_COMMAND

if (OnCommand(wParam, lParam)) return 1L; //①调用 OnCommand是一个CWnd的虚拟函数

else return (LRESULT) DefWindowProc (nMsg, wParam, lParam);⑨

}//消息往父类别推去

pMessageMap = GetMessageMap();

for (; pMessageMap != NULL;pMessageMap = pMessageMap->pBaseMessageMap){

lpEntry = pMessageMap->lpEntries;

printlpEntries(lpEntry);

}

return 0;

}

1. 如果①指向CMyFrameWnd 对象,那么调用的是CFrameWnd:: OnCommand。

2. 如果①指向CMyView 对象,那么调用的是CView:: OnCommand。而因为CView并没有改写OnCommand,所以调用的其实是CWnd:: OnCommand。

BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam){//以第1种情况为例

return CWnd::OnCommand(wParam, lParam); //②

}

BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam){

return OnCmdMsg(0, 0); //③是CCmdTarget 的虚拟函数

}//③CMyFrameWnd/CMyView/CMyDoc的对象使用CFrameWnd/CView/CDoc::OnCmdMsg

//CMyWinApp对象并没有改写OnCmdMsg ,所以调用的是CCmdTarget::OnCmdMsg

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode){

CView* pView = GetActiveView();

if (pView->OnCmdMsg(nID, nCode)) return TRUE;//④

if (CWnd::OnCmdMsg(nID, nCode)) return TRUE;//⑦

CWinApp* pApp = AfxGetApp();

if (pApp->OnCmdMsg(nID, nCode)) return TRUE;//⑧

return FALSE;

}//Frame窗口处理WM_COMMAND 的次序。最先调用的是pView-> OnCmdMsg ④

BOOL CView::OnCmdMsg(UINT nID, int nCode){

if (CWnd::OnCmdMsg(nID, nCode)) return TRUE;//⑤

BOOL bHandled = FALSE;

bHandled = m_pDocument->OnCmdMsg(nID, nCode); //⑥

return bHandled;

}//View窗口处理WM_COMMAND 的次序。最先调用⑤CWnd::OnCmdMsg,CCmdTarget:: OnCmdMsg:

BOOL CCmdTarget::OnCmdMsg(UINT nID, int nCode){

AFX_MSGMAP* pMessageMap;

AFX_MSGMAP_ENTRY* lpEntry;

for (pMessageMap = GetMessageMap() ; pMessageMap != NULL;

pMessageMap = pMessageMap->pBaseMessageMap){

lpEntry = pMessageMap->lpEntries;

printlpEntries(lpEntry);

}

return FALSE; // not handled

}

如果在映射表中找到了对应的消息,就调用对应的处理例程,然后也就结束了二万五千里长征。如果没找到,长征还没有结束,这时候退守回到CView:: OnCmdMsg ,调用⑥CDocument:: OnCmdMsg:

BOOL CDocument::OnCmdMsg(UINT nID, int nCode){

if (CCmdTarget::OnCmdMsg(nID, nCode) return TRUE;

return FALSE;

}

如果在映射表中还是没找到对应消息,这时候退到CFrameWnd::OnCmdMsg,调用⑦CWnd:: OnCmdMsg (也就是CCmdTarge t:: OnCmdMsg)

如果在映射表中还是没找到对应消息,再退回到CFrameWnd:: OnCmdMsg,调用⑧CWinApp :: OnCmdMsg(亦即CCmdTarge t:: OnCmdMsg )

还是没找到对应的消息,退回到⑨CWnd::WindowProc,调用 CWnd:: DefWindowProc。你可以想象,在真正的MFC 中这个成员函数必是调用Windows API 函数:: DefWindowProc。


分别从frame 对象和view 对象中推动消息,消息分一般Windows 消息WM_COMMAND

// test Message Routing

AfxWndProc(0, WM_CREATE, 0, 0, pMyFrame);

AfxWndProc(0, WM_PAINT, 0, 0, pMyView);

AfxWndProc(0, WM_COMMAND, 0, 0, pMyView);

AfxWndProc(0, WM_COMMAND, 0, 0, pMyFrame);

读书人网 >VC/MFC

热点推荐