您的位置:首页 > 编程语言

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

2009-09-22 00:28 453 查看
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; }
通过单步跟踪就看得更加真切了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: