深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
命令傳遞(Command?routing)
?????消息如果是僅僅從派生類流向父類,那就非常簡單了。然而MFC用來處理消息的C++類,并不是單線發展的。document/view也具有處理消息的能力。因此,消息應該有橫向流動的機會。
?????MFC對消息循環的規定為:
????1:若是一般的windows消息(WM_xx)則一定是由派生類流向基類。
????2:如果是WM_COMMAND消息,就非常復雜了。要區分接受者的類型:
??????1:接受者若為Frame窗口:處理次序為:View->?Frame窗口本身->CWinApp類。
??2:接受者若為View?:處理次序為:View本身->Document;
??3:接受者若為Document:處理次序為:Document本身->Document?template
????因此,接下來我們的任務就是仿真以上的消息傳遞路線。
????以下為需要添加的函數:
????全局函數AfxWndProc,它是整個消息循環的起始點,本來應該在CWinThread::Run中被調用,每調用一次就推送一個消息。模擬windows的disPatch函數。
?LRESULT?AfxWndPro(HWND?hWnd,UINT?nMsg,WPARAM??
????????????????????????wParam,LPARAM?lParam,CWnd?*pWnd)
{
???cout<<"AfxWndProc()"<<endl;
???return??AfxCallWndProc?(pWnd,hWnd,nMsg,wParam,lParam);
}
LRESULT?AfxCallWndProc(CWnd*pWnd,HWND?hWnd,UINT?nMsg,
????????????????????????????WPARAM?wParam,LPARAM?lParam)
{
???cout<<"AfxCallWndProc"<<endl;
LRESULT?lResult=pWnd->windowProc(nMsg,wParam,lParam);
return?lResult;
}
全局函數AfxCallWndProc用于調用接受消息的類的消息處理函數。pWnd->WindowProc調用哪個函數,取決于pWnd指向的對象類型。
如果pWnd指向CMyFrameWnd對象,則調用CFrameWnd::WindowProc。因為CFrameWnd斌沒有改寫WindowProc,因此調用的是CWnd::WindowProc。。
????如果pWnd指向CMyView對象,那么調用CView::windowProc。而CMyView沒有改寫WIndowProc所以調用的是CWnd::WindowProc。
????在CWnd::windowProc中,首先判斷消息是否為WM_COMMAND消息,
????如不是,則傳遞給父類進行處理。
????如果是WM_COMMAND消息,CWnd::windowProc調用OnCommand。此函數為虛函數。有以下幾種情況:
???????1:如果this指向CMyFrameWnd對象,則調用的是CFrameWnd::OnComamnd。
???????2:如果this指向CMyView對象,那么調用的是CView::OnCommand。因為CView并沒有改寫OnComamnd所以調用的是CWnd::OnCommand。
bool?CFrameWnd::OnComamnd(WPARAM?wParam,LPARAM?lParam)
{
???cout<<"CFrameWnd::OnCommand()"<<endl;
???return?CWnd::OnCommand(wParam,lParam);
}
bool?CWnd::OnComamnd(WPARAM?wParam,LPARAM?lParam)
{
???cout<<"CWnd::OnComamnd()"<<endl;
???return?OnCmdMsg(0,0);
}
????OnCmdMsg仍然是虛函數,
????1:如果this指向CMyFrameWnd對象,那么調用的是CFrameWnd::OnCmdMsg。
????2:如果this指向CMyView對象,則調用CView::OnCmdMsg。
????3:如果this指向CMyDoc對象,則調用CDocument::OnCmdMsg。
4:如果this指向CM與WinApp對象,則調用CWinApp::??nCmdMsg。因為CWinApp沒有改寫OnCmdMsg因此調用的是CCmdTarget::OnCmdMsg。
Bool?CFrameWnd::OnCmdMsg(UINT?nID,int?nCode)
{
cout<<"CFrameWnd::OnCmdMsg()"<<endl;
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?fasle;
}
bool?CView::OnCmdMsg(UINT?nID,int?nCode)
{
??cout<<"CView::OnCmdMsg()"<<endl;
???if(CWnd::OnCmdMsg(nID,nCode))
?????return?true;
???bool?bHandled=false;
???bHandled=m_pDocument->OnCmdMsg(nID,nCode);
???return?bHandled;
}
Bool?CDocument::OnCmdMsg(UINT?nID,int?nCode)
{
????cout<<"CDocument::OnCmdMsg()"<<endl;
????if(CCmdTarget::OnCmdMsg(nID,nCode))
?????return?true;
????return?false;
}
?????真正的消息傳遞路徑是從OnCmdMsg開始的。在每個類的OnCmdMsg函數中,會調用其他類的OnCmdMsg函數,從而決定每個消息的傳遞路徑。
?????如果消息在前一個OnCmdMsg中被處理,就不會繼續傳遞。如果沒有被處理,則會繼續沿著路徑傳遞下去。無論如何,最終消息的比對是在CCmdTarget類中進行的,只是調用GetMessageMap的this指針不同,會決定調用哪個類的消息映射表。理解這一點很重要!!!
bool?CCmdTarget::OnCmdMsg(UINT?nID,int?nCode)
{
???cout<<"CCmdTarget::OnCmdMsg()"<<endl;
???for(pMessageMap=GetMessageMap();pMessageMap;
?????????????pMessageMap=pMessageMap->pBaseMessageMap()
????{
???????If(找到)
?????????//執行消息處理函數。
????}
}
總結
以上是生活随笔為你收集整理的深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(2740):重读vue电商网站
- 下一篇: 关于深入浅出MFC(1)