求MFC消息映射机制的原理详解或介绍一本介绍其原理的书籍(通俗易懂一些) 5
1个回答
展开全部
MFC的消息映射机制是非常复杂的,我可以在下面简单的介绍一下,具体的请参考侯俊杰的《深入浅出MFC》,这本书用了两章讲解了消息映射机制,作者讲解的非常好懂,强烈推荐!下面我只是大致说说。
在MFC的框架结构下,每一个注册过消息的类都有一个消息数组,盛放着这个类需要处理的消息,把每一个类靠着继承关系用指针连成一个链表,那么,每收到一个消息就顺着这条链表找到注册这个消息的类(从继承的角度看消息查找时的顺序应该和继承关系一致,呈线性,但实际上却有横向流通的消息,这个就比较深入了,请去看那本书),这条链表是用三个宏来建立起来的。
所以,可以进行消息处理的类的头文件里面都会含有DECLARE_MESSAGE_MAP()宏,这个宏主要进行消息映射和消息处理函数的注册和声明。
并且,可以进行消息处理的类的实现文件里一般都含有如下的结构:
BEGIN_MESSAGE_MAP(CChildClass, CBaseClass)
//{{AFX_MSG_MAP(CChildClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这里主要进行消息映射的实现和消息处理函数的实现。关于这三个宏的详细定义和讲解请看那本书中的介绍。
这三个宏是表面上的,在宏的内部则需要其他的技术:
主要涉及到下面两个主要结构:AFX_MSGMAP_ENTRY和AFX_MSGMAP。
其中AFX_MSGMAP_ENTRY结构包含了一个消息的所有相关信息:
nMessage为Windows消息的ID号;
nCode为控制消息的通知码;
nID为Windows控制消息的ID;
nLastID表示如果是一个指定范围的消息被映射的话;
nLastID用来表示它的范围;
nSig表示消息的动作标识;
AFX_PMSG pfn 这个是一个指向和该消息相应的执行函数的指针。
至于AFX_MSGMAP结构,主要作用是两个,一:用来得到基类的消息映射入口地址。二:得到本身的消息映射入口地址。
实际上,MFC把所有的消息一条条填入到AFX_MSGMAP_ENTRY结构中去,形成一个数组,该数组存放了所有的消息和与它们相关的参数。同时通过AFX_MSGMAP能得到该数组的首地址,同时得到基类的消息映射入口地址,这是为了当本身对该消息不响应的时候,就调用其基类的消息响应。详细分析一定要去看那本书。
下面就说说MFC是如何让窗口过程来处理消息的,实际上所有MFC的窗口类都通过滤网函数_AfxCbtFilterHook截获消息,并且在滤网函数_AfxCbtFilterHook中把窗口过程设定为AfxWndProc。原来的窗口过程保存在成员变量m_pfnSuper中。(这么两句话你肯定理解不了。。。)
所以在MFC框架下,一般一个消息的处理过程是这样的。
1.函数AfxWndProc接收Windows操作系统发送的消息。
2.函数AfxWndProc调用函数AfxCallWndProc进行消息处理,相比于win32,这里一个进步是把对句柄的操作转换成对CWnd对象的操作。
3.函数AfxCallWndProc调用CWnd类的方法WindowProc进行消息处理。注意AfxWndProc和AfxCallWndProc都是AFX的全局API函数。而WindowProc已经是CWnd的一个方法,所以可以注意到在WindowProc中已经没有win32中关于句柄或者是CWnd的参数了。
4.方法WindowProc调用方法OnWndMsg进行正式的消息处理,即把消息派送到相关的方法中去处理。实际上在CWnd类中都保存了一个AFX_MSGMAP的结构,而在AFX_MSGMAP结构中保存有所有我们用ClassWizard生成的消息的数组的入口,我们把传给OnWndMsg的message和数组中的所有的message进行比较,找到匹配的那一个消息。实际上系统是通过函数AfxFindMessageEntry来实现的。找到了那个message,实际上就得到一个AFX_MSGMAP_ENTRY结构,而我们在上面已经提到AFX_MSGMAP_ENTRY保存了和该消息相关的所有信息,其中主要的是消息的动作标识和跟消息相关的执行函数。然后我们就可以根据消息的动作标识调用相关的执行函数,而这个执行函数实际上就是通过ClassWizard在类实现中定义的一个方法。这样就把消息的处理转化到类中的一个方法的实现上。
我这只是大致的介绍一下,如果需要详细了解请仔细看《深入浅出MFC》。
在MFC的框架结构下,每一个注册过消息的类都有一个消息数组,盛放着这个类需要处理的消息,把每一个类靠着继承关系用指针连成一个链表,那么,每收到一个消息就顺着这条链表找到注册这个消息的类(从继承的角度看消息查找时的顺序应该和继承关系一致,呈线性,但实际上却有横向流通的消息,这个就比较深入了,请去看那本书),这条链表是用三个宏来建立起来的。
所以,可以进行消息处理的类的头文件里面都会含有DECLARE_MESSAGE_MAP()宏,这个宏主要进行消息映射和消息处理函数的注册和声明。
并且,可以进行消息处理的类的实现文件里一般都含有如下的结构:
BEGIN_MESSAGE_MAP(CChildClass, CBaseClass)
//{{AFX_MSG_MAP(CChildClass)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
这里主要进行消息映射的实现和消息处理函数的实现。关于这三个宏的详细定义和讲解请看那本书中的介绍。
这三个宏是表面上的,在宏的内部则需要其他的技术:
主要涉及到下面两个主要结构:AFX_MSGMAP_ENTRY和AFX_MSGMAP。
其中AFX_MSGMAP_ENTRY结构包含了一个消息的所有相关信息:
nMessage为Windows消息的ID号;
nCode为控制消息的通知码;
nID为Windows控制消息的ID;
nLastID表示如果是一个指定范围的消息被映射的话;
nLastID用来表示它的范围;
nSig表示消息的动作标识;
AFX_PMSG pfn 这个是一个指向和该消息相应的执行函数的指针。
至于AFX_MSGMAP结构,主要作用是两个,一:用来得到基类的消息映射入口地址。二:得到本身的消息映射入口地址。
实际上,MFC把所有的消息一条条填入到AFX_MSGMAP_ENTRY结构中去,形成一个数组,该数组存放了所有的消息和与它们相关的参数。同时通过AFX_MSGMAP能得到该数组的首地址,同时得到基类的消息映射入口地址,这是为了当本身对该消息不响应的时候,就调用其基类的消息响应。详细分析一定要去看那本书。
下面就说说MFC是如何让窗口过程来处理消息的,实际上所有MFC的窗口类都通过滤网函数_AfxCbtFilterHook截获消息,并且在滤网函数_AfxCbtFilterHook中把窗口过程设定为AfxWndProc。原来的窗口过程保存在成员变量m_pfnSuper中。(这么两句话你肯定理解不了。。。)
所以在MFC框架下,一般一个消息的处理过程是这样的。
1.函数AfxWndProc接收Windows操作系统发送的消息。
2.函数AfxWndProc调用函数AfxCallWndProc进行消息处理,相比于win32,这里一个进步是把对句柄的操作转换成对CWnd对象的操作。
3.函数AfxCallWndProc调用CWnd类的方法WindowProc进行消息处理。注意AfxWndProc和AfxCallWndProc都是AFX的全局API函数。而WindowProc已经是CWnd的一个方法,所以可以注意到在WindowProc中已经没有win32中关于句柄或者是CWnd的参数了。
4.方法WindowProc调用方法OnWndMsg进行正式的消息处理,即把消息派送到相关的方法中去处理。实际上在CWnd类中都保存了一个AFX_MSGMAP的结构,而在AFX_MSGMAP结构中保存有所有我们用ClassWizard生成的消息的数组的入口,我们把传给OnWndMsg的message和数组中的所有的message进行比较,找到匹配的那一个消息。实际上系统是通过函数AfxFindMessageEntry来实现的。找到了那个message,实际上就得到一个AFX_MSGMAP_ENTRY结构,而我们在上面已经提到AFX_MSGMAP_ENTRY保存了和该消息相关的所有信息,其中主要的是消息的动作标识和跟消息相关的执行函数。然后我们就可以根据消息的动作标识调用相关的执行函数,而这个执行函数实际上就是通过ClassWizard在类实现中定义的一个方法。这样就把消息的处理转化到类中的一个方法的实现上。
我这只是大致的介绍一下,如果需要详细了解请仔细看《深入浅出MFC》。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询