MFC教程(4)-- 消息映射的实现(2)
2010-03-25 20:33:48 来源:WEB开发网一些消息处理类的OnCmdMsg的实现
从以上论述知道,OnCmdMsg虚拟函数在MFC命令消息的发送中扮演了重要的角色,CFrameWnd的OnCmdMsg实现了MFC的标准命令消息发送路径。
那么,就产生一个问题:如果命令消息不送给边框窗口对象,那么就不会有按标准命令发送路径发送消息的过程?答案是肯定的。例如一个菜单被一个对话框窗口所拥有,那么,菜单命令将送给MFC对话框窗口对象处理,而不是MFC边框窗口处理,当然不会和CFrameWnd的处理流程相同。
但是,有一点需要指出,一般标准的SDI和MDI应用程序,只有主边框窗口拥有菜单和工具条等用户接口对象,只有在用户与用户接口对象进行交互时,才产生命令,产生的命令必然是送给SDI或者MDI程序的主边框窗口对象处理。
下面,讨论几个MFC类覆盖OnCmdMsg虚拟函数时的实现。这些类的OnCmdMsg或者可能是标准MFC命令消息路径的一个环节,或者可能是一个独立的处理过程(对于其中的MFC窗口类)。
从分析CView的OnCmdMsg实现开始。
CView的OnCmdMsg
CView::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
首先,调用CWnd::OnCmdMsg,结果是搜索当前视的类和基类的消息映射数组,搜索顺序是从下层到上层。若某一层实现了对命令消息nID的处理,则调用它的实现函数;否则,调用m_pDocument->OnCmdMsg,把命令消息送给文档类处理。m_pDocument是和当前视关联的文档对象指针。如果文档对象类实现了OnCmdMsg,则调用它的覆盖函数;否则,调用基类(例如CDocument)的OnCmdMsg。
接着,讨论CDocument的实现。
CDocument的 OnCmdMsg
BOOL CDocument::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
首先,调用CCmdTarget::OnCmdMsg,导致当前对象(this)的类和基类的消息映射数组被搜索,看是否有对应的消息处理函数可用。如果有,就调用它;如果没有,则调用文档模板的OnCmdMsg函数(m_pTemplate->OnCmdMsg)把消息送给文档模板处理。
MFC文档模板没有覆盖OnCmdMsg,导致基类CCmdTarget的OnCmdMsg被调用,看是否有文档模板类或基类实现了对消息的处理。是的话,调用对应的消息处理函数,否则,返回FALSE。从前面的分析知道,CCmdTarget类的消息映射数组是空的,所以这里返回FALSE。
CDialog的OnCmdMsg
BOOL CDialog::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
调用CWnd::OnCmdMsg,让对话框或其基类处理消息。
如果还没有处理,而且是控制消息或系统命令或非命令按钮,则返回FALSE,不作进一步处理。否则,调用父窗口的OnCmdmsg(GetParent()->OnCmdmsg)把消息送给父窗口处理。
如果仍然没有处理,则调用当前线程的OnCmdMsg(GetThread()->OnCmdMsg)把消息送给线程对象处理。
如果最后没有处理,返回FALSE。
CMDIFrameWnd的OnCmdMsg
对于MDI应用程序,MDI主边框窗口首先是把命令消息发送给活动的MDI文档边框窗口进行处理。MDI主边框窗口对OnCmdMsg的实现函数的原型如下:
BOOL CMDIFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
如果有激活的文档边框窗口,则调用它的OnCmdMsg(MDIGetActive()->OnCmdMsg)把消息交给它进行处理。MFC的文档边框窗口类并没有覆盖OnCmdMsg函数,所以基类CFrameWnd的函数被调用,导致文档边框窗口的活动视、文档边框窗口本身、应用程序对象依次来进行消息处理。
如果文档边框窗口没有处理,调用CFrameWnd::OnCmdMsg把消息按标准路径发送,重复第一次的步骤,不过对于MDI边框窗口来说不存在活动视,所以省却了让视处理消息的必要;接着让MDI边框窗口本身来处理消息,如果它还没有处理,则让应用程序对象进行消息处理──虽然这是一个无用的重复。
除了CView、CDocument和CMDIFrameWnd类,还有几个OLE相关的类覆盖了OnCmdMsg函数。OLE的处理本书暂不涉及,CDialog::OnCmdMsg将在对话框章节专项讨论其具体实现。
更多精彩
赞助商链接