MFC教程(4)-- 消息映射的实现(2)
2010-03-25 20:33:48 来源:WEB开发网综上所述,标准Windwos消息和应用程序消息中的Registered消息,由窗口过程直接调用相应的处理函数处理:
如果某个类型的窗口(C++类)处理了某条消息(覆盖了CWnd或直接基类的处理函数),则对应的HWND窗口(Winodws window)收到该消息时就调用该覆盖函数来处理;如果该类窗口没有处理该消息,则调用实现该处理函数最直接的基类(在C++的类层次上接近该类)来处理,上述例子中如果CTview不处理WM_CREATE消息,则调用上一层的CWnd::OnCreate处理;
如果基类都不处理该消息,则调用DefWndProc来处理。
消息映射机制完成虚拟函数功能的原理
综合对Windows消息的处理来看,MFC使用消息映射机制完成了C++虚拟函数的功能。这主要基于以下几点:
所有处理消息的类从CCmdTarget派生。
使用静态成员变量_messageEntries数组存放消息映射条目,使用静态成员变量messageMap来唯一地区别和得到类的消息映射。
通过GetMessage虚拟函数来获取当前对象的类的messageMap变量,进而得到消息映射入口。
按照先底层,后基层的顺序在类的消息映射数组中搜索消息处理函数。基于这样的机制,一般在覆盖基类的消息处理函数时,应该调用基类的同名函数。
以上论断适合于MFC其他消息处理机制,如对命令消息的处理等。不同的是其他消息处理有一个命令派发/分发的过程。
下一节,讨论命令消息的接受和处理。
对命令消息的接收和处理
MFC标准命令消息的发送
在SDI或者MDI应用程序中,命令消息由用户界面对象(如菜单、工具条等)产生,然后送给主边框窗口。主边框窗口使用标准MFC窗口过程处理命令消息。窗口过程把命令传递给MFC主边框窗口对象,开始命令消息的分发。MFC边框窗口类CFrameWnd提供了消息分发的能力。
下面,还是通过一个例子来说明命令消息的处理过程。
使用AppWizard产生一个单文档应用程序t。从help菜单选择“About”,就会弹出一个ABOUT对话框。下面,讨论从命令消息的发出到对话框弹出的过程。
首先,选择“ About”菜单项的动作导致一个Windows命令消息ID_APP_ABOUT的产生。Windows系统发送该命令消息到边框窗口,导致它的窗口过程AfxWndProc被调用,参数1是边框窗口的句柄,参数2是消息ID(即WM_COMMAND),参数3、4是消息参数,参数3的值是ID_APP_ABOUT。接着的系列调用如图4-3所示。
下面分别讲述每一层所调用的函数。
前4步同对Windows消息的处理。这里接受消息的HWND窗口是主边框窗口,因此,AfxWndProc根据HWND句柄得到的MFC窗口对象是MFC边框窗口对象。
在4.2.2节谈到,如果CWnd::OnWndMsg判断要处理的消息是命令消息(WM_COMMAND),就调用OnCommand进一步处理。由于OnCommand是虚拟函数,当前MFC窗口对象是边框窗口对象,它的类从CFrameWnd类导出,没有覆盖CWnd的虚拟函数OnCommand,而CFrameWnd覆盖了CWnd的OnCommand,所以,CFrameWnd的OnCommand被调用。换句话说,CFrameWnd的OnCommand被调用是动态约束的结果。接着介绍的本例子的有关调用,也是通过动态约束而实际发生的函数调用。
接着的有关调用,将不进行为什么调用某个类的虚拟或者消息处理函数的分析。
(1)CFrameWnd的OnCommand函数
BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
参数wParam的低阶word存放了菜单命令nID或控制子窗口ID;如果消息来自控制窗口,高阶word存放了控制通知消息;如果消息来自加速键,高阶word值为1;如果消息来自菜单,高阶word值为0。
如果是通知消息,参数lParam存放了控制窗口的句柄hWndCtrl,其他情况下lParam是0。
在这个例子里,低阶word是ID_APP_ABOUT,高阶word是1;lParam是0。
MFC对CFrameWnd的缺省实现主要是获得一个机会来检查程序是否运行在HELP状态,需要执行上下文帮助,如果不需要,则调用基类的CWnd::OnCommand实现正常的命令消息发送。
更多精彩
赞助商链接