这个问题是老问题了,我有点糊涂,希望有人能解释一下
窗口过程DefWindowProc是默认的,被注册成窗口的过程函数了,在Create窗口和InitThread的时候,分别挂了2个钩子函数,因为MFC的消息是走AfxWinProc分发的,所以窗口过程被改了。在代码里确实看到了CreateEx函数了下了钩子,可是好像这个钩子函数在处理完CHBT_CREATEWND后就也被unhook了,我不清楚那个被改了的窗口过程这时又被改成默认的了还是没变?InitThread的时候的钩子挂的那个函数又对消息处理起什么作用呢?还有改窗口过程又说是在SubClass什么方法里改的,可是我没看到调用该方法而且AfxCbtFilterHook钩子也好像是直接setwindowlong的,是在是糊涂了,MFC消息机制到底是怎样的啊?清晰的脉络到底是什么,从初始化开始到消息循环,就想知道这样一个东东MFC处理的脉络到底啥样子,谁知道解答下,十分感谢啊!!!
2个钩子函数:_AfxMsgFilterHook,_AfxCbtFilterHook

解决方案 »

  1.   


    MFC中所有能够进行消息处理的类都是基于CCmdTarget类的,也就是说CCmdTarget类是所有可以进行消息处理类的父类。CCmdTarget类是MFC处理命令消息的基础和核心。在MFC的框架结构下,可以进行消息处理的类的头文件里面都会含有DECLARE_MESSAGE_MAP()宏,这里主要进行消息映射和消息处理函数的声明。
    BEGIN_MESSAGE_MAP(CInheritClass, CBaseClass)
    //{{AFX_MSG_MAP(CInheritClass)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()同时,MFC定义了下面的两个主要结构:
    AFX_MSGMAP_ENTRY
    struct AFX_MSGMAP_ENTRY
    {
    UINT nMessage; // windows message (Windows消息的ID号)
    UINT nCode; // control code or WM_NOTIFY code (控制消息的通知码)
    UINT nID; // control ID (or 0 for windows messages) (Windows控制消息的ID)
    UINT nLastID; // used for entries specifying a range of control id's 
    UINT nSig; // signature type (action) or pointer to message (消息的动作标识)
    AFX_PMSG pfn; // routine to call (or special value) (一个指向和该消息相应的执行函数的指针)
    };AFX_MSGMAP:
    //AFX_MSGMAP主要作用是两个:1,用来得到基类的消息映射入口地址。2,得到本身的消息映射入口地址。
    struct AFX_MSGMAP
    {
    #ifdef _AFXDLL
    const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
    #else
    const AFX_MSGMAP* pBaseMap;
    #endif
    const AFX_MSGMAP_ENTRY* lpEntries;
    };根据以上MFC系统定义的数据结构, MFC把所有的消息一条条填入到AFX_MSGMAP_ENTRY结构中去,形成一个数组,该数组存放了所有的消息和与它们相关的参数。同时通过AFX_MSGMAP能得到该数组的首地址,同时得到基类的消息映射入口地址,这是为了当本身对该消息不响应的时候,就调用其基类的消息响应。3。MFC下消息机制的实现过程:实际上所有MFC的窗口类都通过钩子函数_AfxCbtFilterHook截获消息,并且在钩子函数_AfxCbtFilterHook中把窗口过程设定为AfxWndProc。原来的窗口过程保存在成员变量m_pfnSuper中。所以在MFC框架下,一般一个消息的处理过程是这样的:(1) 函数AfxWndProc接收Windows操作系统发送的消息。
    (2) 函数AfxWndProc调用函数AfxCallWndProc进行消息处理,把对句柄的操作转换成对CWnd对象的操作。
    (3) 函数AfxCallWndProc调用CWnd类的方法WindowProc进行消息处理。
    (注意AfxWndProc和AfxCallWndProc都是AFX的API函数。而WindowProc已经是CWnd的一个方法。所以可以注意到在WindowProc中已经没有关于句柄或者是CWnd的参数了。)
    (4) 方法WindowProc调用方法OnWndMsg进行正式的消息处理,即把消息派送到相关的方法中去处理。如果nWndMsg方法没有对消息进行处理的话,就调用DefWindowProc对消息进行处理。这是实际上是调用原来的窗口过程进行缺省的消息处理。
    第(4)步中消息派送的实现过程:实际上在CWnd类中都保存了一个AFX_MSGMAP的结构,而在AFX_MSGMAP结构中保存有所有我们用ClassWizard生成的消息的数组的入口,我们把传给OnWndMsg的message和数组中的所有的message进行比较,找到匹配的那一个消息。这些由系统通过函数AfxFindMessageEntry来实现。找到了那个message,实际上我们就得到一个AFX_MSGMAP_ENTRY结构,而我们在上面已经提到AFX_MSGMAP_ENTRY保存了和该消息相关的所有信息,其中主要的是消息的动作标识和跟消息相关的执行函数。然后我们就可以根据消息的动作标识调用相关的执行函数,而这个执行函数实际上就是通过ClassWizard在类实现中定义的一个方法。这样就把消息的处理转化到类中的一个方法的实现上。