关闭

关闭

关闭

封号提示

内容

首页 vc 消息映射与命令通知

vc 消息映射与命令通知.doc

vc 消息映射与命令通知

Erica可欣 2018-07-12 评分 0 浏览量 0 0 0 0 暂无简介 简介 举报

简介:本文档为《vc 消息映射与命令通知doc》,可适用于影视/动漫领域,主题内容包含vc消息映射与命令通知vc消息映射与命令通知消息的传递与发送是Windows应用程序的核心所在任何事件的触发与响应均要通过消息的作用才能得以完成。在符等。

vc消息映射与命令通知vc消息映射与命令通知消息的传递与发送是Windows应用程序的核心所在任何事件的触发与响应均要通过消息的作用才能得以完成。在SDK编程中对消息的获取与分发主要是通过消息循环来完成的而在MFC编程中则是通过采取消息映射的方式对其进行处理的。相比而言这样的处理方式要简单许多这也是符合面向对象编程中尽可能隐含实现细节的原则。一个完整的MFC消息映射包括对消息处理函数的原型声明、实现以及存在于消息映射中的消息入口。这几部分分别存在与类的头文件和实现文件中。一般情况下除了对自定义消息的响应外对于标准Windows消息的映射处理可以借助ClassWizard向导来完成。在选定了待处理的Windows消息后向导将会根据消息的不同而生成具有相应函数参数和返回值的消息处理代码框架。下面这段代码给出了一个完成的MFC消息映射过程:在h文件中的声明{{AFXMSG(CMessageMapView)afxmsgvoidOnMove(intx,inty)}}AFXMSGDECLAREMESSAGEMAP()…在cpp文件中的实现BEGINMESSAGEMAP(CMessageMapView,CView){{AFXMSGMAP(CMessageMapView)ONWMMOVE()}}AFXMSGMAPENDMESSAGEMAP()…voidCMessageMapView:OnMove(intx,inty){CView:OnMove(x,y)TODO:Addyourmessagehandlercodehere}这里对Windows标准消息WMMOVE做了消息映射其中用到的BEGINMESSAGEMAP、ENDMESSAGEMAP和头文件中的DECLAREMESSAGEMAP等均是用于消息映射的宏。这些宏声明了在应用程序框架中可用于在系统中浏览所有对象映射的成员变量和函数。除了以上三个比较常见的宏之外MFC还提供了其他一些用于消息映射的宏详情可参见下表:宏名说明DECLAREMESSAGEMAP在头文件声明源文件中所含有的消息映射BEGINMESSAGEMAP标记源文件消息映射的开始ENDMESSAGEMAP标记源文件消息映射的结束ONCOMMAND将特定命令的处理委派给类的一个成员函数ONCONTROL映射一个函数到一个定制控制通知消息。其中定制控制通知消息是从一个控制发送到其父窗口的消息。ONCONTROLRANGE将一个控制ID的范围映射到一个消息处理函数ONCONTROLREFLECT映射一个由父窗口反射回控制的通知消息ONMESSAGE将一个用户自定义消息映射到一消息处理函数ONNOTIFY映射一个控制消息到一个函数ONNOTIFYRANGE映射一个控制ID范围内的控制消息到一个函数ONNOTIFYEX映射一个控制消息到一个函数该成员函数返回FALSE或TRUE来表明通知是否应被传送到下一个对象以进行其他反应。ONNOTIFYEXRANGE映射一个控制ID范围内的控制消息到一个函数该成员函数返回FALSE或TRUE来表明通知是否应被传送到下一个对象以进行其他反应ONNOTIFYREFLECT映射一个控制消息到一个函数。该消息将会被控制的父窗口反射回来。ONREGISTEREDMESSAGE映射一个唯一的消息到一个将要处理该注册消息的函数上。该消息是由RegisterWindowMessage()函数注册的。ONUPDATECOMMANDUI映射一个函数来处理一个用户接口更新命令消息ONUPDATECOMMANDUIRANGE映射一个命令ID的范围到一个更新消息处理函数一般作为基类使用的CWnd类为Windows消息定义了大量窗口消息的缺省处理函数这些函数大部分只是简单地调用了Windows的缺省过程可以在派生类中对其进行重载。但是MFC应用程序框架却并没有象使用普通虚函数那样使用Windows消息处理函数而是通过宏将指定的消息映射到派生类的成员函数。如果MFC仍象普通虚函数一样对消息响应函数进行处理那么CWnd类就要为这上百个消息声明虚函数。而C将为在程序中使用的每一个派生类都提供一个被称作vtable的虚拟函数分配表这个分配表需要为每一个虚函数提供一个字节的入口而不管这些函数在派生类中是否真正被重载这将不能有效利用存储空间。而且对于每一个不同类型的窗口或控件应用程序都要为其提供一个超过字节的虚拟函数分配表来实现对消息的响应。而采用MFC的用宏将Windows消息映射到C成员函数的方式则可避免产生庞大的虚拟函数分配表其消耗的内存是同它所包含的消息入口数量成正比的。消息映射的工作原理前面给出了消息映射的一般形式下面就对消息映射的工作原理做更深入的分析。任何使用了MFC应用程序框架的Windows程序都含有一个从CWinApp派生的应用程序类对象成员函数Run()将被隐含调用其调用的CWinThread过对GetMessage()、TranslateMessage()和类成员函数Run()将通DispatchMessage()等函数的调用完成同WinMain()类似的消息循环。在消息处理中几乎所有的窗口对象都使用AfxWndProc()窗口处理函数并通过一个包含了窗口句柄和对象指针等信息的列表而获取到一个指向对象的指针由此可以调用CWnd的虚函数WindowProc()。WindowProc()函数调用了CWnd的另一个成员函数OnWndMsg()该函数首先检查到达的究竟是消息命令还是通知(Notify)如果是消息就通过消息映射宏DECLAREMESSAGEMAPBEGINMESSAGEMAP和ENDMESSAGEMAP完成对消息的映射。在宏定义中封装了部分代码这些被封装的预定义代码可以在VC安装目录下的"MFCIncludeAfxwinh"中找到在编译时将为编译器所展开。下面给出此预定义代码的实现清单:#ifdefAFXDLL#defineDECLAREMESSAGEMAP()private:staticconstAFXMSGMAPENTRYmessageEntriesprotected:staticAFXDATAconstAFXMSGMAPmessageMapstaticconstAFXMSGMAP*PASCALGetBaseMessageMap()virtualconstAFXMSGMAP*GetMessageMap()const#else#defineDECLAREMESSAGEMAP()private:staticconstAFXMSGMAPENTRYmessageEntriesprotected:staticAFXDATAconstAFXMSGMAPmessageMapvirtualconstAFXMSGMAP*GetMessageMap()const#endif#ifdefAFXDLL#defineBEGINMESSAGEMAP(theClass,baseClass)constAFXMSGMAP*PASCALtheClass:GetBaseMessageMap(){returnbaseClass:messageMap}constAFXMSGMAP*theClass:GetMessageMap()const{returntheClass:messageMap}AFXCOMDATAFXDATADEFconstAFXMSGMAPtheClass:messageMap={theClass:GetBaseMessageMap,theClass:messageEntries}AFXCOMDATconstAFXMSGMAPENTRYtheClass:messageEntries={#else#defineBEGINMESSAGEMAP(theClass,baseClass)constAFXMSGMAP*theClass:GetMessageMap()const{returntheClass:messageMap}AFXCOMDATAFXDATADEFconstAFXMSGMAPtheClass:messageMap={baseClass:messageMap,theClass:messageEntries}AFXCOMDATconstAFXMSGMAPENTRYtheClass:messageEntries={#endif#defineENDMESSAGEMAP(){,,,,AfxSigend,(AFXPMSG)}}图展示了消息映射处理的过程示意。搜寻过程是从CMainWindow的消息入口开始的DECLAREMESSAGEMAPBEGINMESSAGEMAP和ENDMESSAGEMAP等消息映射宏通过搜索派生类消息映射的函数允许访问积累消息映射的入口。如果由CFrameWnd类派生的类CMainWindow没有捕获通常由CFrameWnd捕获的消息那么消息将由相同的由派生类所继承的CFrameWnd类函数捕获。同样如果CFrameWnd类仍没有捕获通常由其父类CWnd捕获的消息则将继续上溯下去。这种消息映射的继承性与C的继承是一致的。另外消息映射函数入口可以在在消息到达时为那些被隐含消息循环所调用的函数从中查看并决定哪一个对象以及对象中的哪一个成员函数应该负责此消息的处理。虽然消息映射的内部工作原理比较复杂但MFC通过预定义宏等手段将其完整的封装了起来展现给开发人员的只是简单明了的MFC消息映射。图消息映射处理过程示意命令和通知命令和通知实际都是一种特殊的消息类型。在SDK编程中菜单和控件的动作均会产生一个WMCOMMAND命令消息通过对消息参数wParam的区分可以识别出具体是哪个控件或菜单发出的命令。在MFC应用程序框架下菜单和控件产生的消息将有所区分选取菜单产生的消息被称作命令而点击控件所产生的消息则被称作通知。由于命令和通知的本质仍是一种消息因此在基本原理上仍是同消息一致的即也是通过消息循环进入OnWndMsg()进而为对应的处理函数所响应。但是在使用上命令和消息还是有区别的其中一个最主要的区别是消息只有CWnd类的派生类所接收而命令和通知则可以为所有从CCmdTarget派生出去的类对象所接收从MFC类的继承关系可以看出除CWnd外CWinThread、CDocument和CDocItem等也都可以接收命令和通知。除此之外命令和通知在从消息循环进入到OnWndMsg()后的这段过程也是同消息传递略有出入的图(a)和(b)分别给出了命令和通知的传递流程:图命令通知传递流程这里CWnd:OnCommand()在检查完各项细节后、CWnd:OnNotify()在检查完不同条件后都调用了虚函数OnCmdMsg()。这样对于不同的菜单项和控件就可以有不同的实现。从下面给出的命令传递过程示例代码可以看出命令通知的传递与消息的映射是非常类似的:头文件{{AFXMSG(CDIPSystemView)afxmsgvoidOnEmboss()afxmsgvoidOnUpdateEmboss(CCmdUI*pCmdUI)}}AFXMSGDECLAREMESSAGEMAP()…源文件BEGINMESSAGEMAP(CDIPSystemView,CScrollView){{AFXMSGMAP(CDIPSystemView)ONCOMMAND(IDMEMBOSS,OnEmboss)ONUPDATECOMMANDUI(IDMEMBOSS,OnUpdateEmboss)}}AFXMSGMAPENDMESSAGEMAP()…voidCDIPSystemView:OnEmboss(){return}…voidCDIPSystemView:OnUpdateStartPos(CCmdUI*pCmdUI){pCmdUIEnable(mbCanUse)}这里ONCOMMAND宏将特定命令的处理同一个类成员函数建立了关联。而宏ONUPDATECOMMANDUI则负责对命令的更新即通过CCmdUI对象控制菜单控件的是否可用或其他一些状态变化的更新。对命令的更新也可以将其理解为存在一个含有每个菜单入口的大表各菜单入口含有菜单是否可用的标志。在显示菜单时通过快速检查该表而做出其所对应的每一个菜单项是否可用的决定。如果可用标志发生了变化该表也将得到及时的更新。小结消息和命令作为VC编程中很基本的一种机制在几乎所有的VC程序中都有所涉及。在学习VC其他编程技术之前必须首先对消息映射机制是如何运做的有一个清楚的认识。本文所述代码在WindowsProfessional下由MicrosoftVisualC下调试通过。

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +1积分

资料评分:

/8
0下载券 下载 加入VIP, 送下载券

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部

举报
资料