MFC深入浅出--命令传递
来源:互联网 发布:中国银行业数据库 编辑:程序博客网 时间:2024/05/18 03:46
Command Routing (命令传递)
MFC对于消息循环的规定:
#若是一般的Windows消息(WM_xxx),则一定是由派生类流向基类,没有旁流的可能。
#若是命令消息WM_COMMAND,就有奇特的路线了。
不管规则是怎么制定的。现在需要一个推动引擎。全局函数AfxWndProc就是推动引擎的起始点。它原本在CwinThread::Run()中被调用。但为了实验目的,我们在main函数中调用它。每调用一次边推送一个消息,这个函数在MFC中MFC中有四个参数,我们加入第五个参数,表示谁获得了消息(成为循环的起点)。例如:
AfxWndProc( 0 ,WM_CREATE ,0 ,0 ,pMyFrame );
表示pMyFrame获得一个WM_CREATE,而
AfxWndProc( 0 ,WM_COMMANDE ,0 ,0 ,pMyFrame );
表示pMyFrame获得一个WM_ COMMANDE.
下面是消息传递的过程:
LRESULT AfxWndProc(HWND hWnd ,UINT nMsg, WPAARAM mParam, LPARAM lParam, Cwnd * pWnd)
{
cout<<” AfxWndProc”<<endl;
return AfxCallWnfProc(pWnd,hWnd,nMsg,wParam,lParam);
}
LRESULT AfxCallWnfProc (CWnd * pWnd ,HWND hWnd ,UINT nMsg, WPAARAM mParam, LPARAM lParam)
{
cout<<”AfxCallWndProc()”<<endl;
LRESULT lResult = pWnd->WindowProc(nMsg,wParam,lParam);
Return lResult;
}
由于WindowProc是虚函数,若pWnd指向CMyFrameWnd对象,则调用CMyFrameWnd::WindowProc。而因为CMyFrameWnd并没有改写WindowProc,所以调用的其实是CWnd:: WindowProc;若pWnd指向CMyView对象,则调用CView::WindowProc。而因为CView并没有改写WindowProc,所以调用的其实是CWnd:: WindowProc。
虽然殊途同归,但意义不同。
CWnd:: WindowProc首先判断消息是否为WM_COMMAND。若不是,事情最简单,就把信息往父类推去,父类再往祖父类推去。每到一个类的消息映射表,原本应该比较AFX_MSGMAP_ENREY的每一个元素,比较成功就调用对应的处理程序。
LRESULT CWnd::WindowProc(UINT nMsg,WPARAM wParam,LPARAM lParam)
{
AFX_MSGMAP * pMessageMap;
AFX_MSGMAP_ENTRY * lpEntry;
If(nMsg==WM_COMMAND) //special case for commands
{
if(oncommand(wParam,lParam)) //…①
return 1L;//command handled
else
return (LRESULT)DefWindowProc(nMsg,wParam,lParam);//⑨
}
pMessageMap = GetMessageMap();
for(;pMessageMap!=NULL; pMessageMap= pMessageMap-> pBaseMessageMap)
{
lpEntry = pMessageMap->lpEntry;
printflpEntries(lpEntry);
}
return 0;
}
如果消息是WM_COMMAND,CWnd::WindowProc调用①处代码。注意oncommand也是一个CWnd的虚函数:若this指向CMyFrameWnd对象,那么调用的是CFrameWnd::OnCommand;若this指向CMyView对象,则调用CView::OnCommand。而因为CView并没有改写OnCpmmand,所以实际调用的是CWnd::OnCommand.
我们以第一种情况为例,再向下看:
BOOL CFrameWnd::OnCommand(WPARAM wParam , LPARAM lParam)
{
cout<<”CFreameWnd::OnCommand()”<<endl;
//…
//route as normal Command
return CWnd::OnCOmmand(wParaM,lParam);//②
}
BOOL CWnd:: OnCommand(WPARAM wParam , LPARAM lParam)
{
cout<<” CWnd::OnCommand()”<<endl;
…
return OnCmdMsg(0,0);//③
}
③处代码OnCmdMsg是CCmdTarget类的虚函数,所以:
#若this指向CMyFrameWnd对象,则调用CMyFrameWnd::OnCmdMsg;
#若this指向CMyView对象,则调用CMyView::OnCmdMsg;
#若this指向CMyDoc对象,则调用CMyDoc::OnCmdMsg;
#若this指向CMyWinApp对象,则调用CMyWinApp::OnCmdMsg;。而因为CwinApp并没有改写OnCmdMsg,所以其实调用的是CCmdTarget::OnCmdMsg。
当前的情况是第一种,于是调用CframeWnd::OnCmdMsg;
BOOL CFrameWnd:: OnCmdMsg(UINT nID ,int nCode)
{
cout<<” CFrameWnd::OnCommand()”<<endl;
//pump through current view First
CView *pView = GetActiveView();
If(pView-> OnCmdMsg(nID,nCode)) //④
Return TRUE;
//then pump through frame
if(CWnd:: OnCmdMsg(nID,nCode))//⑦
return TRUE;
//last but not least,pump through app
CWinApp *pApp = AfxGetApp();
If(pApp-> OnCmdMsg(nID,nCode))//⑧
Return TRUE;
Return FALSE;
}
这个函数反映了Frame窗口处理WM_COMMAND的次序.最先调用的 ④pView->OnCmdMsg,于是:
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 ;
}
这又反映了View窗口处理WM_COMMAND的次序.最好调用的CWnd::OnCmdMsg,而CWnd并未改写OnCmdMsg,所以其实就是调用CCmdTarget::OnCmdMsg:
BOOL CCmdTarget::OnCmdMsg(UINT nID,int nCode)
{
cout<<"CCmdTarget::OnCmdMsg()"<<endl;
//now look through message map to see if it applies to us
AFX_MSGMAP *pMessageMap;
AFX_MSGMAP_ENTRY * lpEntry;
for(pMessageMap = GetMessageMap();pMessageMap!=NULL;
pMessageMap=pMessageMap->pBasemessageMap)
{
lpEntry = pMessageMap-<lpEntry;
printlpEntry(lpEntry);
}
return FALSE:
}
这是一个走访消息映射表的操作.注意,GetMessageMap也是个虚函数(隐藏在DECLARE_MESSAGE_MAP宏定义中),所以它所获得的消息映射表将是this所指对象的影射表.
如果在映射表中找到了对应的消息,就调用对应的处理程序.如果没有找到就退回到CView::OnCmdMsg,调用⑥CDocument::OnCmdMsg:
BOOL CDocument::OnCmdMsg(UINT nID,int nCode)
{
cout<<"CDocument::OnCmdMsg()"<<endl;
if(CCmdTarget::OnCmdMsg(nID,nCode))
return TRUE;
return FALSE;
}
如果在映射表还没有找到对应消息,那么这时退回到CFrameWnd::OnCmdMsg,调用⑦CWnd::OnCmdMsg(即CCmdTarge::OnCmdMsg).
如果在映射表还没有找到对应消息,再退回到CFrameWnd::OnCmdMsg,调用⑧CWinApp::OnCmdMsg(亦即CCmdTarge::OnCmdMsg).
万一还没有找到,就只有退回到CWnd::WindowProc,调用⑨CWnd::DefWindoeProc.
- MFC深入浅出--命令传递
- 命令传递(源自深入浅出MFC)
- 深入浅出MFC:MFC的CommandRouting(命令传递)
- 深入浅出 mfc Command Routing 命令传递
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
- 深入浅出MFC学习笔记(第9章:消息映射与命令传递。)
- 深入浅出MFC学习笔记(第9章:消息映射与命令传递。)
- MFC 消息映射 消息传递MESSAGE_MAP 读深入浅出MFC感悟
- MFC的消息映射与命令传递
- MFC消息映射与命令传递
- MFC - 进程间传递消息命令
- MFC消息映射与命令传递
- MFC中的命令传递(Command Routing)
- MFC消息映射与命令传递
- MFC消息映射与命令传递
- MFC命令传递的内部流程
- MFC消息映射与命令传递
- 管理总结
- JavaBean操作Oracle数据库
- java数据库基础类
- 日本軟件外包設計書常用文型
- 两个简单的画验证码图形程序
- MFC深入浅出--命令传递
- 朝三暮四的我
- Action管理数据表的增加删除和修改工作的跳转和调用执行业务函数
- 介绍一个好用的Grid控件"EjunGrid"
- 自由与共享,对现有版权体系的叛逆
- J2ME低级界面中文输入法
- JAVASWING学习笔记
- 宽带
- 如何使用 Xenocode 、 Dotfuscator 混淆asp.net程序??