第九章:消息映射与命令传递。
本章将会对MFC的消息映射和命令传递机制做深入探讨。
MFC规定了消息传递的路线,消息会按照这个路线传递下去,找不到归宿的话就交给DefWindowProc。
在产生窗口之前,如果我们在创建窗口时指定的窗口类为NULL时,MFC会自动注册五个默认的窗口类,每个窗口类有自己的窗口函数。不同窗口得到的消息应该交由不同的窗口函数来处理。所谓的命令传递机制是为了让消息的流动有线路可循,实现一个巨大的网,实现所有可能的路线。这就是所谓的消息映射图。
WM_COMMAND是来自菜单或工具栏,被称为命令消息。wParam记录着这一消息来自哪个菜单项目。
除了命令消息控件传给父窗口的消息,也是以WM_COMMAND类型的,但是它们被称为notification消息。
Commandtarget即命令的目的地。因此所有派生自CCmdTarget类的类都可以处理命令消息。
派生自CWnd的类可以处理一般的windows消息和COMMAND消息。
DECLARE_MESSAGE_MAP()
BEGIN_MESSAGE_MAP
ON_COMAMND()
END_MESSAGE()
这些宏实现了消息和消息处理函数的映射,不再介绍哦。
在BEGIN和END之间除了ON_COMMAND之外,还可以有其他的形式,标准的windows消息并不需要我们指定处理函数的名称。如:
ON_WM_CHAR();WM_CHAROnChar
ON_WM_CLOSE();WM_CLOSEOnClose
ON_WM_CREATE();WM_CREATEOnCreate
这些宏MFC已经定义好,将标准的消息和消息处理函数对应起来。
AFX_DAT,AFX_DATADEF,AFX_MSG_CALL和afx_msg一样现在还没有被使用。
虽然所有继承自CCmdTarget的类都可以处理命令消息,都应该有DECLARE_MESSAGE_MAP。。。但是CWinThread却没有。它不参与消息处理。因此CWinApp在填写消息映射表是就会跳过CWinThread。
DECLARE_MESSAGE_MAP(CWinApp,CCmdTarget);
消息映射表有C++多态的味道,但是MFC却没有使用多态来实现它,究其原因估计是多态会导致很大的负担。
前面的介绍中,以AfxWinProc作为起点,此处MFC仍以此作为开始,但是却省略了很多的细节。通常消息是在消息队列中等待窗口抓取,但是MFC安装了钩子,就可以提前抓取或抓取不是自己的消息。这是在所有派生自CWnd的对象创建之际发生的。如:
BoolCWnd::CreateEx()
{
。。。
AfxHookWindowCreate(this);
HWNDhWnd=::CreateWindowEx();
...
}
AfxHookWindowCreate安装了WH_CBT类型的钩子,任何窗口显示之前,注册的钩子函数会被调用。
细节不再深入介绍,只要知道以上这些干了些偷天换日的勾当,把注册窗口类时注册的窗口函数,更换为AfxWndProc。于是AfxWndProc便是DispatchMessage的目的地。之所以弄得这么复杂书上说是为了兼容什么3Dconstrols。不懂,暂且放这儿吧。记住结论就是了。
上面可以知道AfxWndProc是消息的源头,这在前面几张也提到过。在此函数内部会调用AfxClassWndProc,后者会调用pWnd->WindowProc();在整个MFC中拥有windowProc的类有CWnd,CControlBar,COleControl,CDialog......具体调用谁的WindowProc要看pWnd的类型。
在CWnd::windowProc中会调用OnWndMsg函数,它是用来分辨并处理消息的专职机构。如果是命令就交给OnCommand处理,如果是通知消息就交给OnNotify处理。之所以要区分命令消息和通知消息是因为它们的上溯路径并不是单纯的只往父类上去,可能有其他路径。而一般的windows消息却沿着直线上溯。
在OnCommand又调用了OnCmdMsg函数。具体调用哪个OnCommand,OnCmdMsg也是不定的,也得看this指针的类型。OnCmdMsg它是专门处理命令消息的函数。
boolCFrameWnd::OnCmdMsg(UINTnID,intnCode)
{
CView*pView=GetActiveView();
if(pView->OnCmdMsg(nID,nCode))//处理则返回否则继续传递。
returntrue;
if(CWnd::OnCmdMsg(nID,nCode))
returntrue;
CWinApp*pApp=AfxGetApp();
if(pApp->OnCmdMsg(nID,nCode)
returntrue;
returnfasle;
}
boolCView::OnCmdMsg(UINTnID,intnCode)
{
cout<<"CView::OnCmdMsg()"<<endl;
if(CWnd::OnCmdMsg(nID,nCode))
returntrue;
boolbHandled=false;
bHandled=m_pDocument->OnCmdMsg(nID,nCode);
returnbHandled;
}
BoolCDocument::OnCmdMsg(UINTnID,intnCode)
{
cout<<"CDocument::OnCmdMsg()"<<endl;
if(CCmdTarget::OnCmdMsg(nID,nCode))
returntrue;
returnfalse;
}
以上就是消息的传递路线,这里跟第三章模拟的命令传递路线是相同的,具体可以第三章。
OnCmdMsg是各类专门对付命令消息的函数。本类处理过后又会调用下一个类的OnCmdMsg,这样命令消息就会不断传递下去。
如果MDI主窗口接收到一个命令消息,主窗口会把消息传递给CMDIChildWnd子窗口。子窗口传递给它对应的视图,视图检查自己的消息映射表,如果没有找到对应项,将其传递给document。Document检查自己的消息映射表,找到对应项则调用该函数,消息传递结束。如果没有找到继续传递,document把该消息传递到documenttemplate对象。如果还是没有找到,则传回到view,view将其传递给MDI子窗口本身。继续传递给CWinApp,交给默认的消息处理函数。
在定义CRuntimeClass时,MessageMapEntries内定义了消息函数的指针类型,
typedefvoid(AFX_MSG_CALL
CCmdTarget:::*AFX_PMSG)(void);
此时消息处理函数指针类型为返回值为空,参数为空,这是不符合实际的,实际使用中会经过类型转换,使其可以接收参数和返回值。
由于消息处理函数的类型各异,MFC使用了AfxSig_来说明消息处理函数的类型。在找到某消息的消息处理函数之后,判断其类型再进行响应转换。
unionMessageMapFunctionsmmf;
mmf.pfn=lpEntry->pfn;
switch(lpEntry->nSig)
{
caseAfxSig_isg:
lResult=(this->*mmf.pfn_is)(LPTSTR)lParam);
break;
caseAfx_Sig_lwl:
lResult=(this->*mmf.pfn_lwl)(wParam,lParam);
break;
caseAfxSig_vv:
(this->*mmf.pfn_vv)();
break;
........
}
AfxSig_is代表参数为LPTSTR字符串,返回值为int.
Afx_lwl代表参数wiewParam和lParam。返回值为LRESULT。
Afx_vv代表参数和返回值都为void.
(this->*mmf.pfn_vv)();中的pfn_vv是unionMessageMapFunctions的一个成员。如
unionMessageMapFunctions
{
AFX_PMSGpfn;
bool(AFX_MSG_CALLCWnd::*pfn_bD)(CDC*);
void(AFX_MSG_CALLCWnd::*pfn_VV)(CDC*);
.............
};
注意MessageMapFunctions是union类型的哦。
真是佩服当年MFC开发人员的智慧!!!!!
相关推荐
深入浅出MFC读书笔记3 在MFC中,Document-View架构是一个非常重要的概念。本文将对Document-View架构中的关键组件进行深入探讨,并对其实现思路进行详细的解析。 首先,让我们来看一下Document的概念。在MFC中,...
### 深入浅出MFC学习笔记:关键知识点解析 #### 一、Windows消息机制与回调函数 在深入探讨MFC之前,我们先来理解Windows操作系统中的消息机制及其核心组成部分——回调函数。 ##### 1.1 Windows消息机制概述 ...
深入浅出MFC读书笔记2是对MFC框架的进一步学习和理解,主要涵盖了MFC的基础概念、类库结构以及程序构建的关键要素。MFC(Microsoft Foundation Classes)是微软为Windows平台开发的应用程序提供的一种类库,它基于...
在压缩包内,除了主教材《深入浅出MFC》高清第二版(书签).pdf外,还有两个辅助文件:VC驿站-C C++ VC 编程 教程 培训 论坛.lnk可能是一个链接,提供了更多C++和MFC相关的学习资源和讨论平台;VC 驿站.txt可能包含...
第九章 消息映射与命令传递 第十章 MFC与对话框 第十一章 Vies功能的加强与重绘效率的提高 第十二章 打印与预览 第十三章 多重文件与多重视图 第十四章 MFC 多线程程序设计 第十五章 站在众人的肩膀――使用...
总的来说,"深入浅出MFC"的学习资源可以帮助开发者从基础到高级全面了解MFC,通过实例和笔记加深理解,从而更高效地开发Windows应用程序。无论是初学者还是有一定经验的程序员,都能从中受益,提升自己的MFC编程能力...
"《深入浅出MFC》读书心得" 《深入浅出MFC》读书心得是 Windows...《深入浅出MFC》读书心得涵盖了 Windows 程序设计的方方面面,包括程序结构、头文件、makefile、消息循环等知识点,为开发者提供了系统性的学习指南。
通过学习《深入浅出MFC》,读者不仅可以掌握MFC的基本用法,还能深入理解其设计哲学,从而更好地利用MFC开发高效、稳定、功能丰富的Windows应用程序。这本书的内容广泛且深入,适合有一定C++基础并且希望在Windows...
### 深入浅出MFC—笔记关键知识点解析 #### 一、Windows消息机制与回调函数 在深入了解MFC之前,我们首先需要理解Windows操作系统的基本工作原理,尤其是消息驱动模型以及回调函数的概念。 **1.1 Windows消息机制...
《深入浅出MFC简体中文版》是一本专注于Microsoft Foundation Classes (MFC) 的技术专著,旨在帮助读者深入理解和应用这一强大的Windows应用程序开发框架。MFC是微软为C++开发者提供的一种库,它封装了Windows API,...
《深入浅出MFC》是侯捷先生撰写的一本关于Microsoft Foundation Classes (MFC) 的经典著作。MFC是微软公司开发的一个C++类库,它封装了Windows API,为开发者提供了一种更加面向对象的方式来编写Windows应用程序。...
《深入浅出MFC》是一本专为程序员设计的详细指南,主要讲解Microsoft Foundation Classes (MFC) 库的使用和开发技术。MFC是微软公司提供的一个C++类库,它封装了Windows API,使得开发者能用面向对象的方式来编写...
- **第9章 消息映射与命令传递** - **消息处理机制**:详细讲解MFC中的消息处理流程。 - **命令传递机制**:探讨MFC中命令处理的实现方式。 - **UI对象状态维护**:讨论如何维护用户界面对象的状态。 - **第10章...
《深入浅出MFC》是一本专为程序员深入理解Microsoft Foundation Classes (MFC) 库设计的书籍。MFC是微软公司开发的一个C++类库,它为Windows应用程序开发提供了强大的支持,使得开发者能够更容易地利用Windows API...
第九章 消息映射与命令传递 第十章 MFC与对话框 第十一章 Vies功能的加强与重绘效率的提高 第十二章 打印与预览 第十三章 多重文件与多重视图 第十四章 MFC 多线程程序设计 第十五章 站在众人的肩膀――使用...
《深入浅出MFC》是一本专为C++程序员深入理解Microsoft Foundation Classes (MFC)框架而编写的经典书籍。MFC是微软公司为Windows平台开发应用程序提供的一种强大的类库,它基于C++,极大地简化了Windows API的使用,...