《MFC篇》消息映射机制

您所在的位置:网站首页 mfc消息队列长度 《MFC篇》消息映射机制

《MFC篇》消息映射机制

2024-07-17 02:29:46| 来源: 网络整理| 查看: 265

消息映射机制 什么是消息映射机制?

MFC使用消息映射机制来处理消息,引入了消息映射表的概念,表中存消息和消息处理函数及二者对应关系。当鼠标点击事件发生时,会产生对应消息,然后去消息映射表中查找对应的消息处理函数并执行。

什么是句柄?

句柄相当于一个编号,Windows对于我们来说相当于一个黑盒,我们只能通过这个编号,也就是句柄来获得我们想要的数据。(个人理解,句柄存了一个地址,地址所在位置存储了一些必须的信息,如,调用打印机句柄,获得打印机信息,也可以调用打印功能)

消息机制为什么要使用宏?

设计者在设计MFC时,尽可能的使MFC的代码要小,速度尽可能快。为了这个目的,设计师使用了很多奇技淫巧,使用宏就是其中之一。

消息映射机制的宏

MFC消息机制的宏有下面几个:

// 1、 DECLARE_MESSAGE_MAP() // 2、 BEGIN_MESSAGE_MAP()(theClass,baseClass) // 3、 END_MESSAGE_MAP() DELCARE_MESSAGE_MAP

DECLARE_MESSAGE_MAP()宏展开:

#define DECLARE_MESSAGE_MAP() private: static const AX_MSGMAP_ENTRY _messageEntries[]; protected: static AFX_DATA const AFX_MSGMAP messageMap; virtual const AFX_MSGMAP* GetMessageMap() const;

从上面定义可以看出,DECLARE_MESSAGE_MAP()做了三件事, (1)定义了一个长度不定的静态数组变量_messageEntries[]; (2)定义了一个静态变量messageMap; (3)定义了一个虚拟函数GetMessageMap();

AFX_MSGMAP_ENTRY和AFX_MSGMAPX

DECLARE_MESSAGE_MAP()宏中的两个对外不公开的结构struct,即AFX_MSGMAP_ENTRY和AFX_MSGMAPX。 AFX_MSGMAP_ENTRY的定义:

struct AFX_MSGMAP_ENTRY { UNIT nMessage;// windows message UNIT nCode;// control code or WM_NOTIFY code UNIT nID;// control ID UNIT nLastID;// used for entries specifying a range of control id’s UNIT nSig;// signature type (action) or pointer to messagge AFX_PMSG pfn;// routine to call (or special value) };

从注释可以看出,AFX_MSGMAP_ENTRY结构实际上定义了消息和处理此消息的函数之间的映射关系。因此静态数组_messageEntries[],实际上定义了一张表,表中每一项指定了消息和消息处理函数的对应关系,也就是消息映射表。nMessage和nCode确定一条消息的内容,nID和nLastID确定了一条消息的来源,nSig和pfn确定了消息处理函数和调用方式。 此外,名字ENTRY也有入口的意思(即消息和消息处理函数之间的映射)。 AFX_MSGMAP的定义:

struct AFX_MSGMAP { const AFX_MSGMAP* pBaseMap; consgt AFX_MSGMAP_ENTRY* lpEntries; }

AFX_MSGMAP定义了两个指针,pBaseMap指向另一个AFX_MSGMAP,lpEntries指针指向消息映射表_messageEntries。通过这种方式,使得在某个类中调用基类的消息处理函数很容易,因此,“父类的消息处理函数是子类的缺省消息处理函数”就“顺理成章”了。

BEGIN_MESSAGE_MAP

作用:定义DECLARE_MESSAGE_MAP宏声明的静态变量。

#define BEEGIN_MESSAGE_MAP(theClass,baseClass) const AFX_MSGMAP* theClass::GetMessageMap() const { return &theClass::messageMap; } AFX_COMDAT const AFX_MSGMAP theClass::messageMap = { &baseClass::messageMap,&theClass::_messageEntries[0]}; AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[]= { #define END_MESSAGE_MAP() {0,0,0,0,AfxSig_end,(AFX_PMSG)0} };

BEGIN_MESSAGE_MAP有两个参数,theClass表示当前类,baseClass表示父类。 BEGIN_MESSAGE_MAO首先定义了函数GetMessageMap的函数体,返回成员变量messageMap的地址。 然后,AFX_COMDAT const AFX_MSGMAP theClass::messageMap=??,初始化了成员变量messageMap。messageMap的pBaseMap指向父类的messageMap,lpEntries指针指向当前类的_messageEntries数组的首地址。 最后,AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[]=??,定义了_messageEntries数组初始化的开始部分代码, 即一个“{”。

END_MESSAGE_MAP

作用:定义_messageEntries数组初始化的结束部分代码,即“{0,0,0,0,AfxSig_end,(AFX_PMSG)0} };”

#define END_MESSAGE_MAP() {0,0,0,0,AfxSig_end,(AFX_PMSG)0} }; 其他宏

在DECLARE_MESSAGE_MAP和END_MESSAGE_MAP之间还有一些宏,如ON_COMMAND、ON_WM_CREATE等,这些宏最终都会被生成一条AFX_MSGMAP_ENTRY结构的数据,并成为消息映射表_messageEntries的一个元素。 以ON_COMMAND宏为例:

#define ON_COMMAND(id,memberFxn) { WM_COMMAND, CN_COMMAND, (WORD)id,(WORD)id, AfxSigCmd_v, static_cast(memberFxn) }

参考 https://blog.csdn.net/weixin_42083441/article/details/109726786 https://www.jianshu.com/p/c1cdba489b88 https://www.cnblogs.com/zzw19940404/p/14008341.html https://blog.csdn.net/lovemysea/article/details/74893961 https://blog.csdn.net/zhangchuan7758/article/details/121653589

消息映射机制入门 消息映射中的消息是什么?

窗口消息一般由三部分组成: 1、一个无符号整数,是消息值 2、消息附带的WPARAM类型的参数 3、消息附带LPARAM类型的参数。其实我们一般说的消息值,也就是一个无符号整数,经常被定义为宏。

消息映射机制的形象比喻

原文链接:https://zhuanlan.zhihu.com/p/489889991

前几天赵工忽然凑到我脸上来,问我晓不晓得MFC的消息机制原理。

当时我正在努力摸鱼,被这猝不及防闯入的笑脸吓的差点打出一套闪电五连鞭。

我说你别逗我了,你干这一行的时间比我吃饭都多,问谁也不应该来问我这菜鸟吧。

赵工笑的脸更大了,一个劲的叫我说说嘛。

我忽然明白过来,他也想摸鱼,那我就不困了。

我们都知道MFC是一种window程序设计,一种基于事件驱动的程序设计模式。

这种事件驱动,主要是消息。

什么叫消息呢?

比如你是键盘侠,那得敲键盘,按下键盘就是消息;

比如你浏览网页,那得用鼠标点击,按下鼠标就是消息;

比如你想看岛国的学习资料,那得有个硬盘吧,插入硬盘就是消息。

在MFC窗口中,我们看到的现象是:我们点了个按钮,触发了消息机制,MFC程序执行了一些我们事先写好的操作。

不过,我们点下按钮或者敲下键盘,首先捕获到这个消息的,并不是程序——而是操作系统。

这就好比你扫微信付款给店家,你以为开开心心付了钱,店家开开心心收到钱了,实际上首先收到这笔钱的,是微信付款的后台系统。

image

操作系统获取到消息后,就会自动将其存入消息队列中,无论你按了多少个消息,就算是网上重拳出击的键盘侠,发出的每一个键盘消息都会被存入消息队列中。

消息队列这东西只有一个特定,那就是先入先出,先存进去的消息会先被派出去。

想一下,假如十个人给店家付款,先付款的反而店家没有先收到钱,店家慌了,你也慌了,估计怎么也得上演一集霍元甲大战黄飞鸿的好戏。

image

消息队列一收到存进来消息,高兴坏了,来活了。

它们就负责将消息按照顺序一个一个派送给应用程序,丝毫不敢怠慢,打工人没得选择。

经过了消息——操作系统——消息队列——应用程序,MFC应用程序才在真正接收到了消息。

image

然后应用程序会把消息再分发给操作系统,让操作系统去执行响应函数。

但是应用程序也做了些东西的,它负责将消息进行翻译,虽然再分发。

image

为什么要翻译?

很简单啊,就比如说组合键,一套CTRL+C,CTRL+V,你不翻译一下,系统真以为你是想发CTRL,C,CRTL,V这几个信号。

翻译完成后才会分发给操作系统,由操作系统来执行窗口过程。

image

消息驱动和事件驱动的异同

参考链接:https://blog.csdn.net/li_xunhuan/article/details/105574498 参考链接:https://www.zhihu.com/question/30393750

消息驱动和事件驱动的共同点,都是先有一个事件,事件产生相应的消息,再把消息放入消息队列,由需要的项目获取。他们的区别是消息是谁产生的。 以鼠标点击为例: 1、消息驱动:鼠标只管自己点击,不需要和系统过多的交互,消息由系统(或者第三方程序)循环检测,来捕获消息放入消息队列,消息对于鼠标点击事件来说是被动产生,高内聚。 2、事件驱动:鼠标点击产生点击事件后,要向系统发送消息“我点击了”的消息,消息是主动产生的。再发送到消息队列中。事件往往会将事件源包装起来。 备注:事件源:发生事件的对象。(即当前操作的对象)

消息驱动和事件驱动优缺点: 1、消息驱动耦合低,跨模块好用。 2、事件驱动耦合高,同模块内好用。 3、事件驱动是侵入式的,霸占主循环;消息驱动非侵入式的,将主循环该怎样设计的自由留给用户。 4、如果你在设计一个东西举棋不定,那么可以看看win32的GetMessage,本身就是一个耦合度极低的接口,又足够自由,接口任何语言都很方便,也可以在其基础上再封装成事件驱动。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭