


下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MFC中消息映射机制分析
摘要:MFC以层次结构组织起来,比较庞杂,尤其是它的消息映射机制,更是涉及到很多底层的东西。本文通过对整个消息映射机制进行系统的分析,可以帮助程序开发人员更好地了解MFC,进行可视化编程。关键词:消息驱动;消息映射;MFC程序设计1引言微软公司提供的MFC基本类库(MicrosoftFoundationClasses),是进行可视化编程时使用最为流行的一个类库。MFC封装了大部分WindowsAPI函数和Windows控件,使得程序的开发变得简单,极大的缩短了程序的开发周期。MFC独创的Document/View框架结构,能够将管理数据的代码和显示数据的程序代码分开,并且设计了一套方便的消息映射和命令传递机制,方便程序员的开发使用。其中消息映射机制本身比较庞大和复杂,对它的分析和了解无疑有助于我们写出更为合理的高效的程序。这里我们分析一下MFC的消息映射机制,以了解MFC是如何对Windows的消息加以封装,方便用户的开发。2SDK下的消息机制实现首先,简单回顾一下SDK下我们是如何进行Windows的程序开发的。Windows程序的运行是依靠外部发生的事件来驱动的,事件由操作系统捕捉,以消息的形式进入消息队列,然后通过消息循环从队列中不断取出消息,送到对应的窗口过程里处理。相对于DOS程序,Windows是以WinMain作为程序的入口点,以下就是一个简化的Win32程序的主体,通过while语句实现消息循环:WinMain(…){MSGmsg;RegisterClass(…);//注册窗口类CreateWindow(…);
//创建窗口ShowWindow(…);
//显示窗口UpdateWindow(…);While(GetMessage(&msg,…)){//消息循环TranslateMessage(…);DispatchMessage(…);}returnmsg.wParam;}其中,msg代表消息,程序是通过GetMessage函数从和某个线程相对应的消息队列里面把消息取出来并放到消息变量msg里面。然后TranslateMessage函数用来把键盘消息转化并放到响应的消息队列里面,最后DispatchMessage函数把消息分发到相关的窗口过程去处理。窗口过程根据消息的类型对不同的消息进行相关的处理。在SDK编程过程中,用户需要在窗口过程中分析消息的类型及其参数的含义,然后做不同的处理,相对比较麻烦;而MFC把消息调用的过程给封装起来,使用户能够通过ClassWizard方便的使用和处理Windows的各种消息。3MFC中的消息映射机制在MFC的框架结构下,“消息映射”是通过巧妙的宏定义,形成一张消息映射表格来进行的。这样一旦消息发生,Framework就可以根据消息映射表格来进行消息映射和命令传递。首先在需要进行消息处理的类的头文件(.H)里,都会含有DECLARE_MESSAGE_MAP()宏,声明该类拥有消息映射表格:classCscribbleDoc:publicCdocument{
…DECLARE_MESSAGE_MAP()};然后在类应用程序文件(.CPP)实现这一表格BEGIN_MESSAGE_MAP(CInheritClass,CBaseClass)
//{{AFX_MSG_MAP(CInheritClass)ON_COMMAND(ID_EDIT_COPY,OnEditCopy)………
//}}AFX_MSG_MAPEND_MESSAGE_MAP()这里主要进行消息映射的实现,把它和消息处理函数联系在一起。其中出现三个宏,第一个宏是BEGIN_MESSAGE_MAP有两个参数,分别是拥有消息表格的类,及其父类。第二个宏是ON_COMMAND,指定命令消息的处理函数名称。第三个宏是END_MESSAGE_MAP()作为结尾符号。中间的奇怪符号//}}和//{{,是ClassWizard产生的,对程序无影响。观察DECLARE_MESSAGE_MAP的定义:#defineDECLARE_MESSAGE_MAP()\private:\staticconstAFX_MESSAGE_ENTRY_messageEntries[];\protected:\staticAFX_DATAconstAFX_MSGMAPmessageMap;\virtualconstAFX_MSGMAP*GetMessageMap()const;\里面又包含了MFC新定义的两个数据结构,如下:AFX_MSGMAP_ENTRYstructAFX_MSGMAP_ENTRY{
UINTnMessage;//windowsmessage
UINTnCode;
//controlcodeorWM_NOTIFYcode
UINTnID;//controlID(or0forwindowsmessages)
UINTnLastID;
//usedforentriesspecifyingarangeofcontrolid's
UINTnSig;
//signaturetype(action)orpointertomessage#
AFX_PMSGpfn;
//routinetocall(orspecialvalue)};和AFX_MSGMAPstructAFX_MSGMAP{
constAFX_MSGMAP*pBaseMap;
constAFX_MSGMAP_ENTRY*lpEntries;};其中AFX_MSGMAP_ENTRY结构包含了一个消息的所有相关信息,而AFX_MSGMAP主要作用有两个,一是用来得到基类的消息映射入口地址。二是得到本身的消息映射入口地址。实际上,MFC把所有的消息一条条填入到AFX_MSGMAP_ENTRY结构中去,形成一个数组,该数组存放了所有的消息和与它们相关的参数。同时通过AFX_MSGMAP能得到该数组的首地址,同时得到基类的消息映射入口地址。当本身对该消息不响应的时候,就可以上溯到基类的消息映射表寻找对应的消息响应。现在我们来分析MFC是如何让窗口过程来处理消息的,实际上所有MFC的窗口类都通过钩子函数_AfxCbtFilterHook截获消息,并且在钩子函数_AfxCbtFilterHook中把窗口过程设定为AfxWndProc。原来的窗口过程保存在成员变量m_pfnSuper中。在MFC框架下,一般一个消息的处理过程是这样的。(1)函数AfxWndProc接收Windows操作系统发送的消息。(2)函数AfxWndProc调用函数AfxCallWndProc进行消息处理,这里一个进步是把对句柄的操作转换成对CWnd对象的操作。(3)函数AfxCallWndProc调用CWnd类的方法WindowProc进行消息处理。(4)WindowProc调用OnWndMsg进行正式的消息处理,即把消息派送到相关的方法中去处理。在CWnd类中都保存了一个AFX_MSGMAP的结构,而在AFX_MSGMAP结构中保存有所有我们用ClassWizard生成的消息的数组的入口,我们把传给OnWndMsg的message和数组中的所有的message进行比较,找到匹配的那一个消息。实际上系统是通过函数AfxFindMessageEntry来实现的。找到了那个message,实际上我们就得到一个AFX_MSGMAP_ENTRY结构,而我们在上面已经提到AFX_MSGMAP_ENTRY保存了和该消息相关的所有信息,其中主要是消息的动作标识和相关的执行函数。然后我们就可以根据消息的动作标识调用相关的执行函数,而这个执行函数实际上就是通过ClassWizard在类实现中定义的一个方法。这样就把消息的处理转化到类中的一个方法的实现上。(5)如果OnWndMsg方法没有对消息进行处理的话,就调用DefWindowProc对消息进行处理。这是实际上是调用原来的窗口过程进行缺省的消息处理。所以如果正常的消息处理的话,MFC窗口类是完全脱离了原来的窗口过程,用自己的一套体系结构实现消息的映射和处理。即先调用MFC窗口类挂上去的窗口过程,再调用原先的窗口过程。用户面对的消息参数将不再是固定的wParam和lParam,而是和消息类型具体相关的参数。比如和消息WM_LButtonDown相对应的方法OnLButtonDown的两个参数是nFlags和point。nFlags表示在按下鼠标左键的时候是否有其他虚拟键按下,point更简单,就是表示鼠标的位置。同时MFC窗口类消息传递中还提供了两个函数,分别为WalkPreTranslateTree和PreTranslateMessage。我们知道利用MFC框架生成的程序,都是从CWinApp开始执行的,而CWinapp实际继承了CWinThread类。在CWinThread的运行过程中会调用窗口类中的WalkPreTranslateTree方法。而WalkPreTranslateTree方法实际上就是从当前窗口开始查找愿意进行消息翻译的类,直到找到窗口没有父类为止。在WalkPreTranslateTree方法中调用了PreTranslateMessage方法。实际上PreTranslateMessage最大的好处是我们在消息处理前可以在这个方法里面先做一些事情。举一个简单的例子,比如我们希望在一个CEdit对象里,把所有的输入的字母都以大写的形式出现。我们只需要
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度合伙企业合伙份额转让与区块链技术应用协议
- 2025年度企业员工工作环境改善与劳动合同变更
- 宠物店装修垫资合同
- 商业步行街居间合同模板
- 2025年度健康养生馆合伙开店合同
- 科技与休闲的结合电竞酒店会员权益探索
- 2025至2030年智能PTC自控温加热电缆项目投资价值分析报告
- 科技与艺术的融合研究生学术研究与职业规划的新思路
- 2025年中国铅脖套市场调查研究报告
- 2025年中国装配式公路钢桥市场调查研究报告
- 2025年度光伏电站光伏组件回收处理合同示范文本
- 2025年春季少先队工作计划及安排表(附:少先队每月工作安排表)
- 中央2025年公安部部分直属事业单位招聘84人笔试历年参考题库附带答案详解
- 《教育强国建设规划纲要(2024-2035年)》全文
- 体育老师篮球说课
- GB/T 45015-2024钛石膏综合利用技术规范
- 未来畜牧养殖业人才需求分析与发展策略-洞察分析
- 2024CSCO小细胞肺癌诊疗指南解读
- 《真希望你也喜欢自己》房琪-读书分享
- 中国服装零售行业发展环境、市场运行格局及前景研究报告-智研咨询(2025版)
- 2024-2025学年全国中学生天文知识竞赛考试题库(含答案)
评论
0/150
提交评论