MFC六大关键技术之仿真学习笔记(八)
2015-06-07 14:16
741 查看
前一节写到,在类关系中我们已经建立了一种消息映射的机制,消息具体是如何在类中传递的,是一个值得我们去研究的问题,待我一一道来。
*Command Routing(命令传递)
实现消息的纵向流动,我们并不希望消息只呈单线发展,我们更渴望得到的是走访映射表的功能。
这是MFC的消息泵,展示出了各个函数的调用顺序,假若CMyFrameWnd收到WM_COMMAND消息,那么消息将会尝试在数种路线传递,就像以下:
在消息进行遍历的途中,我们能发现最多的就是虚函数。
我来理一下仿真的流程:
先上函数成员表:
(1)一般Windows消息:
AfxWndProc -> AfxCallWndProc -> CWnd::WindowProc -> AfxFindMessageEntry;
(2)CMyFrameWnd 得到 WM_COMMAD
AfxWndProc -> AfxCallWndProc -> CWnd::WindowProc
LRESULT CWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
AFX_MSGMAP* pMessageMap;
AFX_MSGMAP_ENTRY* lpEntry;
if (nMsg == WM_COMMAND)
{
if (OnCommand(wParam,lParam))
{
return 1L;
}
else
{
return (LRESULT)DefWindowProc(nMsg, wParam, lParam);
}
}
pMessageMap = GetMessageMap();
for (; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMessageMap)
{
lpEntry = pMessageMap->lpEntries;
printlpEntries(lpEntry);
}
return 0;
}
-> (virtual)CFrameWnd::OnCommad [OnCommand(wParam,lParam)]
BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
return CWnd::OnCommand(wParam, lParam);
}
-> CWnd::OnCommad [CWnd::OnCommand(wParam,lParam)]
BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
return OnCmdMsg(0, 0);
}
-> (virtual)CFrameWnd::OnCmdMsg [OnCmdMsg(0, 0)]
BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode)
{
CView* pView = GetActiveView();
if (pView->OnCmdMsg(nID,nCode))
{
return TRUE;
}
if (CWnd::OnCmdMsg(nID,nCode))
{
return TRUE;
}
CWinApp* pApp = AfxGetApp();
if (pApp->OnCmdMsg(nID, nCode))
{
return TRUE;
}
return FALSE;
}初见端倪,消息从这里呈多线流动:
线路①:-> CView::OnCmdMsg [pView->OnCmdMsg(nID,nCode)]
BOOL CView::OnCmdMsg(UINT nID, int nCode)
{
if (CWnd::OnCmdMsg(nID,nCode))
{
return TRUE;
}
BOOL bHandled = FALSE;
bHandled = m_pDocument->OnCmdMsg(nID, nCode);
return bHandled;
}1.->(virtual)CCmdTarget::OnCmdMsg [CWnd::OnCmdMsg(nID,nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
1221 CMyView
122 CView
12 CWnd
1 CCmdTarget
2.->CDocument::OnCmdMsg -> CCmdTarget::OnCmdMsg [m_pDocument->OnCmdMsg(nID, nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
131 CMyDoc
13 CDocument
1 CCmdTarget
线路②: ->(virtual)CCmdTarget::OnCmdMsg
[CWnd::OnCmdMsg(nID,nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
1211 CMyFrameWnd
121 CFrameWnd
12 CWnd
1 CCmdTarget
线路③: ->(virtual)CCmdTarget::OnCmdMsg
[pApp->OnCmdMsg(nID, nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
1111 CMyWinApp
111 CWinApp
1 CCmdTarget
消息到达CCmdTarget::OnCmdMsg以后,(virtual)GetMessageMap对消息映射表进行遍历,如果找到匹配消息进行处理,未找到则返回FALSE,交由DefWindowProc进行处理。这样仿真直观的解释了消息是如何在MFC框架中进行流动的。
到此,MFC的关键仿真技术已经学习完成,学习笔记暂时写到这里。
相关代码下载:http://download.csdn.net/detail/u010125463/8784495
*Command Routing(命令传递)
实现消息的纵向流动,我们并不希望消息只呈单线发展,我们更渴望得到的是走访映射表的功能。
这是MFC的消息泵,展示出了各个函数的调用顺序,假若CMyFrameWnd收到WM_COMMAND消息,那么消息将会尝试在数种路线传递,就像以下:
在消息进行遍历的途中,我们能发现最多的就是虚函数。
我来理一下仿真的流程:
先上函数成员表:
(1)一般Windows消息:
AfxWndProc -> AfxCallWndProc -> CWnd::WindowProc -> AfxFindMessageEntry;
(2)CMyFrameWnd 得到 WM_COMMAD
AfxWndProc -> AfxCallWndProc -> CWnd::WindowProc
LRESULT CWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
AFX_MSGMAP* pMessageMap;
AFX_MSGMAP_ENTRY* lpEntry;
if (nMsg == WM_COMMAND)
{
if (OnCommand(wParam,lParam))
{
return 1L;
}
else
{
return (LRESULT)DefWindowProc(nMsg, wParam, lParam);
}
}
pMessageMap = GetMessageMap();
for (; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMessageMap)
{
lpEntry = pMessageMap->lpEntries;
printlpEntries(lpEntry);
}
return 0;
}
-> (virtual)CFrameWnd::OnCommad [OnCommand(wParam,lParam)]
BOOL CFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
return CWnd::OnCommand(wParam, lParam);
}
-> CWnd::OnCommad [CWnd::OnCommand(wParam,lParam)]
BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
return OnCmdMsg(0, 0);
}
-> (virtual)CFrameWnd::OnCmdMsg [OnCmdMsg(0, 0)]
BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode)
{
CView* pView = GetActiveView();
if (pView->OnCmdMsg(nID,nCode))
{
return TRUE;
}
if (CWnd::OnCmdMsg(nID,nCode))
{
return TRUE;
}
CWinApp* pApp = AfxGetApp();
if (pApp->OnCmdMsg(nID, nCode))
{
return TRUE;
}
return FALSE;
}初见端倪,消息从这里呈多线流动:
线路①:-> CView::OnCmdMsg [pView->OnCmdMsg(nID,nCode)]
BOOL CView::OnCmdMsg(UINT nID, int nCode)
{
if (CWnd::OnCmdMsg(nID,nCode))
{
return TRUE;
}
BOOL bHandled = FALSE;
bHandled = m_pDocument->OnCmdMsg(nID, nCode);
return bHandled;
}1.->(virtual)CCmdTarget::OnCmdMsg [CWnd::OnCmdMsg(nID,nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
1221 CMyView
122 CView
12 CWnd
1 CCmdTarget
2.->CDocument::OnCmdMsg -> CCmdTarget::OnCmdMsg [m_pDocument->OnCmdMsg(nID, nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
131 CMyDoc
13 CDocument
1 CCmdTarget
线路②: ->(virtual)CCmdTarget::OnCmdMsg
[CWnd::OnCmdMsg(nID,nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
1211 CMyFrameWnd
121 CFrameWnd
12 CWnd
1 CCmdTarget
线路③: ->(virtual)CCmdTarget::OnCmdMsg
[pApp->OnCmdMsg(nID, nCode)]
此线到达顶端,如被处理返回TRUE。
路线为:
1111 CMyWinApp
111 CWinApp
1 CCmdTarget
消息到达CCmdTarget::OnCmdMsg以后,(virtual)GetMessageMap对消息映射表进行遍历,如果找到匹配消息进行处理,未找到则返回FALSE,交由DefWindowProc进行处理。这样仿真直观的解释了消息是如何在MFC框架中进行流动的。
到此,MFC的关键仿真技术已经学习完成,学习笔记暂时写到这里。
相关代码下载:http://download.csdn.net/detail/u010125463/8784495
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- C++中拷贝构造函数的应用详解
- C++中引用(&)的用法与应用实例分析
- C++使用CriticalSection实现线程同步实例
- Visual C++中MFC消息的分类
- C++智能指针实例详解