深入MFC中WM_COMMAND命令消息的传递
来源:互联网 发布:国外网络商务大赛 编辑:程序博客网 时间:2024/06/18 14:46
我们都知道,MFC将windows消息系统进行了高度的抽象和封装,其根本原理是运用C++的高级特性并结合一定的设计模式(如工厂模式,模板方法等)来实现的。一般的windows消息(WM_XXX),则一定是由派生类流向基类,没有旁流的可能。如果是命令消息(WM_COMMAND),那就有比较奇特的路线了。下面就针对多文档/单文档(Document-View)、对话框两种应用程序比较讨论WM_COMMAND消息的传递处理过程。讨论前首先得明确命令消息的来源,命令消息一般是用户选择某个菜单项,或一个加速键被翻译,或一个子控件发送一个通知消息给它的父窗口时产生的。对一个菜单而言,消息接收者是Frame窗口或拥有它的对话框;对一个工具栏而言,消息接收者是它的父窗口。两种应用程序命令消息处理流程如下图所示。
从上图可知,文档视图型的处理路线是先向下再向上,而对话框型的路线是一直向上,消息接收者只有一个,而处理者次序有多个,每个处理者内部首先都是调用根基类CCmdTarget的OnCmdMsg虚函数,在这个函数内逐级向基类遍历消息映射表,根据命令ID和通知码找到对应的消息映射结构体AFX_MSGMAP_ENTRY,如果找到再处理这个命令消息,否则返回FALSE,退回到this对象所在的OnCmdMsg函数进行下一步处理。如果到最后一层都没有找到对应命令的消息映射,则返回到系统的默认处理DefWindowProc。再综合考虑下,如果一个对话框接收到了一个命令消息例如是点击它的子控件工具栏某个按钮发出的,而这个对话框类没有添加相应的ON_COMMAND映射,就会进入到它的父窗口类OnCmdMsg函数进行处理,如果这个父窗口正好是Frame窗口,那么命令消息的处理流程就由上图右边转到左边了。而最终命令消息能否得处理,就看上图5种对象(Frame、View、Document、Dialog、App、Thread)是否添加了对应的ON_COMMAND映射。到此为止,我们已经明确了WM_COMMAND消息的处理流程,但是发现最终处理却是由收到消息的窗口传递的,不是消息通知者自己处理的,有的时候为了提高代码的封装性,可能需要自己处理这些命令比较方便,比如有一个工具栏CPlayToolBar子类从CToolBar继承,有播放、暂停、停止3个按钮,它的父窗口是CPlayDialog对话框。按照常规,这3个按钮命令事件的处理一般是在CPlayDialog类中3个ON_COMMAND映射宏和处理函数的,但如果在CPlayToolBar类中添加3个ON_COMMAND映射宏和处理函数,是得不到处理的,其原因在于对话框型的路线是一直向上,再者MFC中没有对应的命令反射ON_COMMAND_REFLECT这个宏。为了能使CPlayToolBar类自己处理这3个按钮命令事件,就需要从CPlayDialog类中转移路线,使之流向其子窗口工具栏,这样CPlayToolbar 类就得到了自己处理的机会。具体操作是重载CPlayToolBar和CPlayDialog的OnCommand虚函数, CPlayDialog代码如下所示:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/dot.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://www.cppblog.com/Images/dot.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://www.cppblog.com/Images/dot.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
CPlayToolBar类代码如下所示:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/dot.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/dot.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cppblog.com/Images/dot.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
现在,3个按钮命令事件能在CPlayToolBar类中独立处理了,这样一来就提高了代码的封装性,简化了父窗口CPlayDialog类的处理。
- 深入MFC中WM_COMMAND命令消息的传递
- 深入MFC中WM_COMMAND命令消息的传递
- 深入MFC中WM_COMMAND命令消息的传递
- 深入MFC中WM_COMMAND命令消息的传递
- 深入MFC中WM_COMMAND命令消息的传递
- 深入MFC中WM_COMMAND命令消息的传递
- MFC中WM_COMMAND的消息响应顺序
- MFC命令消息(WM_COMMAND)的传送路径
- MFC框架中WM_COMMAND消息响应顺序
- MFC框架中WM_COMMAND消息响应顺序
- MFC框架中WM_COMMAND消息响应顺序
- MFC框架中WM_COMMAND消息响应顺序
- MFC框架中WM_COMMAND消息响应顺序
- MFC框架中WM_COMMAND消息响应顺序
- 命令消息WM_COMMAND
- MFC中关于基于对话框的应用程序的WM_COMMAND消息的流动路径
- MFC框架中WM_COMMAND消息响应顺序 分享
- MFC的消息映射与命令传递
- ./PHONY
- linux shell if 参数
- JS导出 excel
- YOUYOU部署MongoDB系列之三(副本集配置 持续更新)
- WindowsPE用法【系统收藏】
- 深入MFC中WM_COMMAND命令消息的传递
- 运行时创建多边形刚体
- siverlight datagrid 导出xml或csv格式,保持颜色一致性
- Android中Activity之间访问互传参数
- 用JS来控制键盘上的一些事件
- sleep(), usleep()和[NSThread sleepForTimeInterval:]
- DOM的用法,以及window.onload……eval()
- Xdebug安装与使用
- C#中的线程与同步 ManualResetEvent用法