深度解析VC中的消息(下)

qianshuipangge

qianshuipangge

2016-02-19 19:04

下面图老师小编要跟大家分享深度解析VC中的消息(下),简单的过程中其实暗藏玄机,还是要细心学习,喜欢还请记得收藏哦!

前面,我们分析了消息的基本理论和基本的函数及用法,接下来,我们将进一步讨论消息传递在MFC中的实现。

  MFC消息的处理实现方式

  初看MFC中的各种消息,以及在头脑中根深蒂固的C++的影响,我们可能很自然的就会想到利用C++的三大特性之一:虚拟机制来实现消息的传递,但是经过分析,我们看到事情并不是想我们想象的那样,在MFC中消息是通过一种所谓的消息映射机制来处理的。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  为什么呢?在潘爱民老师翻译的《Visual C++技术内幕》(第4版)中给出了详细的原因说明,我再简要的说一遍。在CWnd类中大约有110个消息,还有其它的MFC的类呢,算起来消息太多了,在C++中对程序中用到的每一个派生类都要有一个vtable,每一个虚函数在vtable中都要占用一个4字节大小的入口地址,这样一来,对于每个特定类型的窗口或控件,应用程序都需要一个440KB大小的表来支持虚拟消息控件函数。

  如果说上面的窗口或控件可以勉强实现的话,那么对于菜单命令消息及按钮命令消息呢?因为不同的应用程序有不同的菜单和按钮,我们怎么处理呢?在MFC库的这种消息映射系统就避免了使用大的vtable,并且能够在处理常规Windows消息的同时处理各种各样的应用程序的命令消息。

  说白了,MFC中的消息机制其实质是一张巨大的消息及其处理函数的一一对应表,然后加上分析处理这张表的应用框架内部的一些程序代码.这样就可以避免在SDK编程中用到的繁琐的CASE语句。

    MFC的消息映射的基类CCmdTarget

  如果你想让你的控件能够进行消息映射,就必须从CCmdTarget类中派生。CCmdTarget类是MFC处理命令消息的基础、核心。MFC为该类设计了许多成员函数和一些成员数据,基本上是为了解决消息映射问题的,所有响应消息或事件的类都从它派生,例如:应用程序类、框架类、文档类、视图类和各种各样的控件类等等,还有很多。

  不过这个类里面有2个函数对消息映射非常重要,一个是静态成员函数DispatchCmdMsg,另一个是虚函数OnCmdMsg。

  DispatchCmdMsg专门供MFC内部使用,用来分发Windows消息。OnCmdMsg用来传递和发送消息、更新用户界面对象的状态。

  CCmdTarget对OnCmdMsg的默认实现:在当前命令目标(this所指)的类和基类的消息映射数组里搜索指定命令消息的消息处理函数。

  这里使用虚拟函数GetMessageMap得到命令目标类的消息映射入口数组_messageEntries,然后在数组里匹配命令消息ID相同、控制通知代码也相同的消息映射条目。其中GetMessageMap是虚拟函数,所以可以确认当前命令目标的确切类。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  如果找到了一个匹配的消息映射条目,则使用DispachCmdMsg调用这个处理函数;

  如果没有找到,则使用_GetBaseMessageMap得到基类的消息映射数组,查找,直到找到或搜寻了所有的基类(到CCmdTarget)为止;

  如果最后没有找到,则返回FASLE。

  每个从CCmdTarget派生的命令目标类都可以覆盖OnCmdMsg,利用它来确定是否可以处理某条命令,如果不能,就通过调用下一命令目标的OnCmdMsg,把该命令送给下一个命令目标处理。通常,派生类覆盖OnCmdMsg时,要调用基类的被覆盖的OnCmdMsg。

  在MFC框架中,一些MFC命令目标类覆盖了OnCmdMsg,如框架窗口类覆盖了该函数,实现了MFC的标准命令消息发送路径。必要的话,应用程序也可以覆盖OnCmdMsg,改变一个或多个类中的发送规定,实现与标准框架发送规定不同的发送路径。例如,在以下情况可以作这样的处理:在要打断发送顺序的类中把命令传给一个非MFC默认对象;在新的非默认对象中或在可能要传出命令的命令目标中。

    消息映射的内容

    通过ClassWizard为我们生成的代码,我们可以看到,消息映射基本上分为2大部分:

    在头文件(.h)中有一个宏DECLARE_MESSAGE_MAP(),他被放在了类的末尾,是一个public属性的;与之对应的是在实现部分(.cpp)增加了一章消息映射表,内容如下:

    BEGIN_MESSAGE_MAP(当前类, 当前类的基类)

       file://{{AFX_MSG_MAP(CMainFrame)
         消息的入口项
       file:/

展开更多 50%)
分享

猜你喜欢

深度解析VC中的消息(下)

编程语言 网络编程
深度解析VC中的消息(下)

深度解析VC中的消息(上)

编程语言 网络编程
深度解析VC中的消息(上)

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

解析VC++6中的指针

编程语言 网络编程
解析VC++6中的指针

VC6.0下利用消息实现内部进程通讯

编程语言 网络编程
VC6.0下利用消息实现内部进程通讯

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

深度解析光圈

摄影 人像摄影 静物摄影 光圈
深度解析光圈

VB与VC混合编程中处理消息的方法

编程语言 网络编程
VB与VC混合编程中处理消息的方法

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

XML入门教程:使用CSS显示XML

XML入门教程:使用CSS显示XML

VC6.0中如何让new操作失败后抛出异常?

VC6.0中如何让new操作失败后抛出异常?
下拉加载更多内容 ↓