深入浅出MFC_消息映射的实现

一,对Windows消息进行分类:队列消息与非队列消息,系统消息与应用程序消息。

二,对消息结构MSG和Windows以及MFC消息处理进行介绍。

三,将MFC处理的消息分成三类:windows消息(前缀以WM_开头,WM_COMMAND除外),控制通知消息(控制子窗口发送给父窗口的WM_COMMAND通知消

  息),命令消息(来自菜单、工具栏按钮、加速键等用户接口对象的WM_COMMAND通知消息,属于应用程序自己定义的消息)。

四,讲述MFC实现消息映射的方法,DECLARE_MESSAGE_MAP 与 BEGIN_MESSAGE_MAP END_MESSAGE_MAP 的实现。特别是对变量

  AFX_MSGMAP_ENTRY _messageEntries[], AFX_MSGMAP messageMap   以及对函数 _GetBaseMessageMap()  GetMessageMap()

  的作用的讲述。 以及其他MFC常用的消息映射的宏(,MFC根据消息的不同和消息处理方式的不同,把消息映射划分成若干类别,每一类的消息映射至少有一

  个共性:消息处理函数的原型相同。对每一类消息映射,MFC定义了一个宏来简化初始化消息数组的工作。例如,前文提到的ON_COMMAND宏用来映射命令消

  息,只要指定命令ID和消息处理函数即可,因为对这类命令消息映射条目,其他四个属性都是固定的)。

五、讲述CCmdTarget类,CCmdTarget类是MFC消息映射的基础、核心,CCmdTarget类有两个与消息映射密切相关的函数OnCmdMsg(虚拟,用来传递和发送

  消息、更新用户界面对象的状态)与DispatchCmdMsg(静态,用于分发windows消息)。(在OLE应用中,CCmdTarget是MFC处理模块状态的重要环节,

  它起到了传递模块状态的作用:其构造函数获取当前模块状态,并保存在成员变量m_pModuleState里头。)

六、MFC的所有窗口都使用同一窗口过程,消息或者直接由窗口过程调用相应的消息处理函数处理,或者按MFC命令消息派发路径送给指定的命令目标处理。

  (把MFC窗口对象(该对象必须已经创建了)和刚刚创建的Windows窗口对象捆绑在一起,建立它们之间的映射(见后面模块-线程状态);然后,调

  用::SetWindowLong设置窗口过程为AfxWndProc,并保存原窗口过程在窗口类成员变量m_pfnSuper中,这样形成一个窗口过程链。)

七、Windows消息的接收与处理过程:Windows调用窗口过程AfxWndProc(),AfxWndProc()调用 AfxCallWndProc(),

  AfxCallWndProc()调用 CWnd::WindowProc(),CWnd::WindowProc()调用 CWnd::OnWndMsg(),

  CWnd::OnWndMsg()调用 相应的消息处理函数(如:CTview::OnCreate())。

  “CWnd::WindowProc”表示CWnd类的虚拟函数WindowProc被调用,并不一定当前对象是CWnd类的实例,事实上,它是CWnd派生类CTview类的实例。

八、CWnd或者派生类的对象调用OnWndMsg搜索本对象或者基类的消息映射数组,寻找当前消息的消息处理函数。如果当前对象或者基类处理了当前消息,则必定

  在其中一个类的消息映射数组中匹配到当前消息的处理函数。

  消息匹配是一个比较耗时的任务,为了提高效率,MFC设计了一个消息缓冲池,把要处理的消息和匹配到的消息映射条目(条目包含了消息处理函数的地址)以及

  进行消息处理的当前类等信息构成一条缓冲信息,放到缓冲池中。如果以后又有同样的消息需要同一个类处理,则直接从缓冲池查找到对应的消息映射条目就可以

  了。MFC用哈希查找来查询消息映射缓冲池。消息缓冲池相当于一个哈希表,它是应用程序的一个全局变量,可以放512条最新用到的消息映射条目的缓冲信息,

  每一条缓冲信息是哈希表的一个入口。

  

如果在消息缓冲池中没有找到匹配,则搜索当前对象的消息映射数组,看是否有合适的消息处理函数。

如果匹配到一个消息处理函数,则把匹配结果加入到消息缓冲池中,即填写该条消息对应的哈希表入口:

nMsg=message;

pMessageMap=this->GetMessageMap;

lpEntry=查找结果

然后,调用匹配到的消息处理函数。否则(没有找到),使用_GetBaseMessageMap得到基类的消息映射数组,查找和匹配;直到匹配成功或搜寻了所有的基类(到CCmdTarget)为止。

如果最后没有找到,则也把该条消息的匹配结果加入到缓冲池中。和匹配成功不同的是:指定lpEntry为空。这样OnWndMsg返回,把控制权返还给AfxCallWndProc函数,AfxCallWndProc将继续调用DefWndProc进行缺省处理。

 

九、调用处理函数的过程就是转换映射条目的pfn指针为适当的函数类型并执行它:MFC定义了一个成员函数指针mmf,首先把消息处理函数的地址赋值给该函数指针,然后根据消息映射条目的nSig值转换指针的类型。但是,要给函数指针mmf赋值,必须使该指针可以指向所有的消息处理函数,为此则该指针的类型是所有类型的消息处理函数指针的联合体(union MessageMapFunctions mmf)。

 

十、命令消息的接收与处理过程:

  Windows调用窗口过程AfxWndProc(),AfxWndProc()调用 AfxCallWndProc(),

  AfxCallWndProc()调用 CWnd::WindowProc(),CWnd::WindowProc()调用 CWnd::OnWndMsg(),

  CWnd::OnWndMsg()调用 CFrameWnd::OnCommand(),CFrameWnd::OnCommand()调用 CWnd::OnCommand(),

  CWnd::OnCommand() 调用 CFrameWnd::OnCmdMsg(), CFrameWnd::OnCmdMsg()调用 CCmdTarget::OnCmdMsg(),

  CCmdTarget::OnCmdMsg() 调用 CCmdTarget::DispatchMessage(), CCmdTarget::DispatchMessage() 调用 消息处理函数。

十一、讲述扩展消息映射宏与消息的多次处理,以及一些消息处理类的OnCmdMsg()、OnCommand()的实现。

十二、讲述控制通知消息的接收与处理以及消息反射的原理(首先需要从适当的MFC窗口派生出一个控制窗口类,然后使用ClassWizard给它添加消息映射条目,指

   定它处理感兴趣的反射消息),反射消息被直接派发给控制子窗口,省却了消息发送的过程。

十三、对更新命令的接收与处理,状态更新函数用来处理给该对象的CN_UPDATE_COMMAND_UID的通知消息。

  

 

转载于:https://www.cnblogs.com/hedantou/archive/2010/09/11/1823725.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值