090921(星期一):MFC消息路由6, Frame8代码分析,GetMessageMap获取了谁的Map

本文详细介绍了如何通过替换宏为代码的方式调试MFC的消息映射机制,包括具体步骤及调试过程中观察到的现象,帮助理解MFC框架下消息处理的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Monday, September 21, 2009

一、宏替换为代码进行调试

Frame8消息分发AfxWndProc(0, WM_CREATE, 0, 0, pMyFrame);

进入LRESULT CWnd::WindowProc(WM_CREATE, 0, 0)

之后:

 

// 调试跟不进去,模拟MFC都做成宏了。

// 消息映射的知识就在这儿了,可以参考0914的笔记。

// 获取消息映射指针

       pMessageMap = GetMessageMap();

// 遍历消息

       for (; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMessageMap)

       {

              lpEntry = pMessageMap->lpEntries;

              printlpEntries(lpEntry);

       }

       return 0; // add by JJHou. if find, should call lpEntry->pfn,

       // otherwise should call DefWindowProc.

上面的语句究竟是如何进行的,使用单步调试的方法加深印象。

1,  备份四个源文件

 

2,  CMyFrameWnd类相关的宏使用代码替换

#define DECLARE_MESSAGE_MAP()  

static AFX_MSGMAP_ENTRY _messageEntries[];  

static AFX_MSGMAP messageMap;  

virtual AFX_MSGMAP* GetMessageMap() const;

 

#define BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)  

       AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const

       { return &CMyFrameWnd::messageMap; }

 

       AFX_MSGMAP CMyFrameWnd::messageMap =

       {

&(CFrameWnd::messageMap),

       (AFX_MSGMAP_ENTRY*) &(CMyFrameWnd::_messageEntries)

};

       AFX_MSGMAP_ENTRY CMyFrameWnd::_messageEntries[] =

       {

 

ON_COMMAND(CMyFrameWndid, 0)

{ WM_COMMAND, 0, (WORD) CMyFrameWndid, (WORD) CMyFrameWndid, AfxSig_vv, (AFX_PMSG)memberFxn },

 

#define END_MESSAGE_MAP()  

{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }   };

 

3,  替换之后的代码

class CMyFrameWnd : public CFrameWnd

{

public:

       CMyFrameWnd();

       ~CMyFrameWnd() {

       }

//     DECLARE_MESSAGE_MAP()

    static AFX_MSGMAP_ENTRY _messageEntries[];  

    static AFX_MSGMAP messageMap;  

    virtual AFX_MSGMAP* GetMessageMap() const;

};

 

 

//BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)

//ON_COMMAND(CMyFrameWndid, 0)

//END_MESSAGE_MAP()

 

AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const

{ return &CMyFrameWnd::messageMap; }

 

AFX_MSGMAP CMyFrameWnd::messageMap =

{

    &(CFrameWnd::messageMap),

    (AFX_MSGMAP_ENTRY*) &(CMyFrameWnd::_messageEntries)

};

 

AFX_MSGMAP_ENTRY CMyFrameWnd::_messageEntries[] =

{

    { WM_COMMAND, 0, (WORD) CMyFrameWndid, (WORD) CMyFrameWndid,  AfxSig_vv, (AFX_PMSG)0 },

 

    { 0,          0,                     0,                   0, AfxSig_end, (AFX_PMSG)0 }  

};

 

4、调试时就可以清楚的看见,this指针的类型是CMyFrameWnd,不是CFrameWnd,更不是CWnd

消息栈:

AfxWndProc(0, WM_CREATE, 0, 0, pMyFrame);

return AfxCallWndProc(pMyFrame, 0, WM_CREATE, 0, 0);

LRESULT lResult = pMyFrame ->WindowProc(WM_CREATE, 0, 0);

WindowProc函数在被调用时,代码是CWnd中定义的函数代码

LRESULT CWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)

{

       AFX_MSGMAP* pMessageMap;

       AFX_MSGMAP_ENTRY* lpEntry;

       if (nMsg == WM_COMMAND) // special case for commands

       {

              if (OnCommand(wParam, lParam))

                     return 1L; // command handled

              else

                     return (LRESULT)DefWindowProc(nMsg, wParam, lParam);

       }

       pMessageMap = GetMessageMap();

       for (; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMessageMap)

       {

              lpEntry = pMessageMap->lpEntries;

              printlpEntries(lpEntry);

       }

       return 0; // add by JJHou. if find, should call lpEntry->pfn,

       // otherwise should call DefWindowProc.

}

 

但是this指针是指向CMyFrameWnd的。

 

至于pMyFrame在声名的时候是CFrameWnd类型,而this是指向CMyFrameWnd的这个问题,完全是和虚函数表现一致,尽管声名成CFrameWnd类型:

CFrameWnd* pMyFrame

但是系统非常清楚它的实际类型。

 

总之,在GetMessageMap时,获取的是

AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const

{ return &CMyFrameWnd::messageMap; }

通过单步跟踪就看得更加真切了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值