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

2016-02-19 19:04 8 1 收藏

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

【 tulaoshi.com - 编程语言 】

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

  MFC消息的处理实现方式

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

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

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

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

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

    MFC的消息映射的基类CCmdTarget

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

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

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

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

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

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

  如果找到了一个匹配的消息映射条目,则使用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:/

来源:http://www.tulaoshi.com/n/20160219/1619941.html

延伸阅读
一、静态链接库         1.静态链接库的生成方法         在vc下建立一个新项目,项目类型选择win32 static library,然后在项目中加入.h.cpp.c文件,编译链接后就会生成一个静态链接库.lib文件。         如果想要取得尽量好...
标签: 心理健康
脾气暴躁是很多人在日常的生活中都会遇到的,或是自己就是这样的人。而人是不会无缘无故的发脾气的,特别是脾气暴躁的人。而不同的人脾气暴躁的原因也是不同的,今天图老师小编就为大家详细的介绍一下孕妇、小孩、老人等脾气暴躁的原因及解决方法。 目录 1、了解什么是脾气暴躁 2、脾气暴躁的原因 3、小孩脾气暴躁的原...
1、windows的消息驱动体系 在windows系统中,消息传递是实现对乡间通信和控制的主要手段。可以额系统都以消息驱动的方式工作。系统中发生的用户输入操作、显示信息的改变、系统环境参数变化等所有时间都以系统定义消息的形式出现在相关的应用程序和窗口。所以程序设计的主要任务就是为这些消息的处理设计代码。 在应用程序中,发...
标签: iPhoneX 智能手机
iPhoneX深度解析,内置神秘芯片 规格参数 屏幕尺寸5.8英寸,重量174克,高度143.6mm,宽度和厚度分别为70.9mm、7.7mm,2436 * 1125 像素分辨率,458 ppi。 背部后置双摄,为1200万像素广角镜头(F/1.8光圈)+1200万像素长焦镜头(F/2.4光圈)组合,支持人像模式背景虚化。 处理器:A11 Bionic采用6核64位架构,集成M11...
标签: PS PS教程
305911是什么?就是一个数学表达式,也就是0.3R+0.59G+0.11B。在photoshop中,它究竟是计算什么的一个数学表达式?有人说是lab中的明度;也有人说它是灰度模式中的灰度;也有人说它是RGB模式中的亮度(也就是直方图中的亮度)。这对操作者来讲研究它意义并不大,图像的操作有更多的主观成份。但对研究者来讲,弄清它究竟...

经验教程

925

收藏

56
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部