课件06_MFC消息映射和消息路由分析
mfc消息映射和消息处理

映射宏把一个Windows 消息和其消息处理函数联 映射宏把一个 Windows消息和其消息处理函数联 结起来。 结起来。
►在类的实现源文件中用
BEGIN_MESSAGE_MAP(derived class) 和
class,base
END_MESSAGE_MAP()宏来定义消息映射 END_MESSAGE_MAP()宏来定义消息映射。 宏来定义消息映射。
回顾
利用应用程序向导(AppWizard)工具 利用应用程序向导(AppWizard)工具 可以建立哪3 可以建立哪3种类型的应用程序? 应用程序向导生成了哪些文件? 如何使用classwizard向导? 如何使用classwizard向导?
如何添加一个成员变量? 如何添加一个成员函数? 如何添加一个新类? 如何添加消息响应函数?
2. 命令消息
3. 控件通知消息
消息映射及消息响应
► MFC 采 用 消 息 映 射 ( Message
பைடு நூலகம்
Map ) 机 制 取 代 结构来处理消息。 C/C++语言中的 C/C++语言中的switch-case结构来处理消息。 语言中的switch-case结构来处理消息
► MFC消息映射机制包括一组消息映射宏。一条消息 MFC消息映射机制包括一组消息映射宏。 消息映射机制包括一组消息映射宏
// 用户自定义的消息映射宏
. . . . . . //}}AFX_MSG_MAP END_MESSAGE_MAP()
注意: 注意 : 特殊注解“//{{AFX_MSG_MAP”是ClassWizard类 向导用于维护消息映射宏的标记,用户不要删除注解轻易 修改注解内的代码。
4. 用户自定义消息
谈谈MFC中的消息映射

谈谈MFC中的消息映射作者:未知文章来源:网络引言:众所周知,windows是基于消息驱动的,作好消息处理是WINDOWS编程的关键任务之一,用VC制作WINDOWS程式同样离不开消息的处理。
虽然VC++6的类向导可以完成绝大部分工作,但不幸的是,它并不能完成所有的工作。
这就要求我们对 VC中消息的处理有一个比较清淅的认识。
只有这样才可能在必要的时候亲自动手完成一些复杂的消息映射处理。
在MFC中消息是通过一种所谓的消息映射机制来处理的。
其实质是一张消息及其处理函数的一一对应表以及分析处理这张表的应用框架内部的一些程序代码.这样的好处是可以避免像早期的SDK编程一样需要罗列一大堆的CASE语句来处理各种消息.由于不同种类的消息其处理方法是不同的,所以我们有必要先弄清楚 WINDOWS消息的种类。
背景:WINDOWS 消息的种类WINDOWS中消息主要有以下三种类型:1、标准的WINDOWS消息:这类消息是以WM_为前缀,不过WM_COMMAND例外。
例如: WM_MOVE、WM_QUIT等.2、命令消息:命令消息以WM_COMMAND为消息名.在消息中含有命令的标志符ID,以区分具体的命令.由菜单,工具栏等命令接口对象产生.3、控件通知消息:控件通知消息也是以WM_COMMAND为消息名.由编辑框,列表框,子窗口发送给父窗口的通知消息.在消息中包含控件通知码.以区分具体控件的通知消息.其中标准的WINDOWS消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理.相对标准WINDOWS消息及控件通知消息而言,命令消息的处理对象范围就广得多.它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。
方法:不同种类消息的映射方法。
在以上三种消息中,标准的WINDOWS消息映射是相当简单的。
可直接通过类向导完成不同消息的映射处理,所以不在本文讨论之列。
凡是从CcmdTarget类派生的类都可以有消息映射.消息映射包括如下两方面的内容:在类的定义文件中(.H)中加上一条宏调用:DECLARE_MESSAGE_MAP()通常这条语句中类定义的最后.在类的实现文件(.CPP)中加上消息映射表:BEGIN_MESSAGE_MAP(类名,父类名)………..消息映射入口项.……….END_MESSAGE_MAP( )幸运的是除了某些类(如没有基类的类或直接从CobjectO类派生的类)外.其它许多类均可由类向导生成.尽管生成的类只是一个框架,需要我们补充内容.但消息映射表已经为我们加好了.只是入口项有待我们加入.命令消息映射入口项是一个ON_COMMAND的宏.比如文件菜单下的"打开…"菜单(ID 值为ID_FILE_OPEN)对应的消息映射入口项为:ON_COMMAND(ID_FILE_NEW,OnFileOpen)加入消息映射入口项之后需要完成消息处理函数.在类中消息处理函数都是类的成员函数,要响应一个消息,就必须定义一个该消息的处理函数.定义一个消息处理函数包括以下三方面的内容.1.在类定义中加入消息处理函数的函数原型(函数声明)2.在类的消息映射表中加入相应的消息映射入口项.3.在类的实现中加入消息处理函数的函数体.需要说明的是消息处理函数的原型一定要以afx_msg打头.比如:afx_msg OnFileOpen();// 函数原型作为约定.消息处理函数一般以On打头但有时我们可能想用一个消息处理函数来处理一批消息。
MFC原理(PPT)

采用MFC编程的优点: 编程的优点: 采用 编程的优点 使用标准化的程序代码结构,有利于程序员之 间的交流. Visual C++为MFC提供了大量的工具支持,提高 了编程效率.如利用MFC AppWizard创建MFC 应 用 程 序 框 架 , 利 用 ClassWizard 方 便 地 对 Windows消息进行管理. MFC 应 用 程 序 的 效 率 较 高 , 只 比 传 统 的 Windows C程序低5%左右.并且,在MFC应用 程序中还允许混合使用传统的Windows API函数. 其它优势:完全支持Windows所有的函数,控件, 消息,菜单及对话框;具有良好的稳定性和可 移植性,更符合微软的风格等.
6.2.2 MFC体系结构 体系结构 MFC主要组成部分:类,宏和全局函数. 类是MFC中最主要的内容.MFC类是以层次结 构方式组织起来的.MFC中的类分成两部分,除 了一些辅助类,大多数的MFC类是直接或间接从 根类CObject派生而来. 几乎每一个派生层次都与一具体的Windows实例 相对应,如文档类,窗口类和视图类等. MFC宏主要功能:消息映射,运行时对象类型服 务,诊断服务,异常处理. MFC约定:全局函数以"Afx"为前缀,全局变量 以"afx"为前缀.
Mfc42UD.lib MfcO42D.lib MfcD42D.lib Nafxcw.lib NafxcwD.lib gdi32.lib user32.lib kernel32.lib msvcrt.lib msvcrtd.lib libcmt.lib libc.lib
MFCxxUD.DLL的导入函数库(Unicode Debug版) MFCOxxD.DLL的导入函数库(OLE Debug版) MFCDxxD.DLL的导入函数库(Database Debug版) MFC静态链接库(Release版) MFC静态链接库(Debug版) GDI32.DLL的导入函数库 USER32.DLL的导入函数库 KERNEL32.DLL的导入函数库 MSVCRT.DLL(C运行函数库)的导入函数库 MSVCRTD.DLL(Debug版C运行函数库)的导入函数库 C运行函数静态链接库(多线程) C运行函数静态链接库(单线程)
mfc原理和消息映射

MFC思想win32程序中创建一个窗口的过程:设计窗口阶段(由WNDCLASS结构描述部分)、窗口的注册及创建显示过程、消息循环部分。
win32用标准的C语言代码实现,是面向过程的。
在MFC中采用了面向对象的思想,即用面向对象的C++思想对以上代码进行了封装,也就是说将一些对窗口进行操作的API的函数封装到了一个类中,以下我将用简短的代码来演示一下这个过程:class CWnd{public:HWND m_hWnd;BOOL Create();BOOL ShowWindow();};BOOL CWnd::Create(){WNDCLASS wndClass;wndClass.style=CS_HREDRAW;wndClass.lpfnWndProc=(WNDPROC)DefWndProc;wndClass.cbClsExtra=0;wndClass.cbWndExtra=0;wndClass.hInstance=hInstance;wndClass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));wndClass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));LOGBRUSH lgbr;lgbr.lbStyle=BS_SOLID;lgbr.lbColor=RGB(192,192,0);lgbr.lbHatch=0;wndClass.hbrBackground=CreateBrushIndirect(&lgbr);wndClass.lpszMenuName=NULL;wndClass.lpszClassName="mycls";RegisterClass(&wndClass);HWND hWnd;m_hWnd=CreateWindow("mycls","窗口标题",WS_OVERLAPPEDWINDOW,0,NULL,NULL,hInstance,NULL);if(m_hWnd!=NULL)return true;elsereturn false;}BOOL CWnd::ShowWindow(){return ShowWindow(hWnd,nCmdShow);}为了保证代码和以前的执行方式一样,Winmain()函数可以写成如下形式:int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){CMyWnd m_wnd;m_wnd.Create();m_wnd.ShowWindow();MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return true;}此时,如果再写一个新的类来对剩下的代码进行封装,代码如下:class CWinApp{public:CWnd * m_pMainWnd;BOOL InitInstance();BOOL Run();CWinApp ();};CWinApp:: CWinApp (){if(InitInstance())Run();}BOOL CWinApp::InitInstance(){CWnd m_wnd;m_pMainWnd=&m_wnd;m_pMainWnd->Create();m_pMainWnd->ShowWindow();return true;}BOOL CWinApp::Run(){MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return true;}CWinApp theApp;int PASCAL WinMain() {}Windows消息的产生:1用户按键或者鼠标操作可以产生消息,如WM_KEYDOWN,WM_LBUTTONDOWN等;2系统可以自己产生消息,如,创建窗口的时候会产生WM_CREATE,WM_TIMER等;3应用程序间可以定义自己的消息,在应用程序间进行消息通讯;Windows消息的分类:1窗口消息(Windows Message):通常跟窗口的移动、创建,关闭等操作有关。
MFC消息映射

消息映射的实现Windows消息概述Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。
这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
消息的分类队列消息和非队列消息从消息的发送途径上看,消息分两种:队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
这里,对消息队列阐述如下:Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
系统消息和应用程序消息从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER (0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。
消息结构和消息处理消息的结构为了从消息队列获取消息信息,需要使用MSG结构。
消息映射 mfc

主要内容
3.1 事件驱动程序机制
3.2 消息的结构及类别
3.3 MFC消息映射原理
3.4 消息映射的实现形式
3.5 自定义消息处理
3.1 事件驱动程序机制
事件
用户对交互界面进行操作(例如操作鼠标、键盘、改变 窗口、选择菜单项等);或者程序的某种特定运行(窗口 的创建显示、窗口客户区中被显示数据修改引起的重绘操 作)都会引起事件的产生。
启动
Winmain,RegisterClass,CreateWindow……
消息处理
Getmessage/Dispatchmessage window procedure various windows API
输入姓名 输入第1次成绩 输入第2次成绩 输入第3次成绩
结束
计算平均成绩
基于事件触发而运行的应用程序必须是完全面向 消息处理的,即始终按如下步骤循环:
主要参数:
hWnd: message: wParam: lParam: 接收消息的窗口句柄 WM_XXX 随 WM_XXX 而变 随 WM_XXX 而变
产生途径:
·窗口范围内的交互操作产生; ·系统框架产生的窗口消息; ·程序根据需要发送窗口消息。
举例:
WM_CREATE
The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. The window procedure of the new window receives this message after the window is created, but before the window becomes visible. The message is sent before the CreateWindowEx or CreateWindow function returns.
MFC消息映射及消息处理函数原型
afx_msg void memberFxn();
ON_EN_SETFOCUS(<id>, <memberFxn>)
afx_msg void memberFxn();
ON_EN_UPDATE(<id>, <memberFxn>)
afx_msg void memberFxn();
ON_NOTIFY_EX_RANGE(<wNotifyCode>, <id>, <idLast>, <memberFxn>)
afx_msg BOOL memberFxn(UINT, NMHDR*, LRESULT*);
ON_NOTIFY_RANGE(<wNotifyCode>, <id>, <idLast>, <memberFxn>)
afx_msg void memberFxn();
ON_STN_ENABLE(<id>, <memberFxn>)
afx_msg void memberFxn();
标准Windows消息( WM_xxx )的对应规则:
消息映射
对应处理函数原型
ON_WM_ACTIVATE()
afx_msg void OnActivate(UINT, CWnd*, BOOL);
afx_msg void memberFxn(UINT);
ON_CONTROL_REFLECT(<wNotifyCode>, <memberFxn>)
afx_msg void memberFxn();
可视化教学PPT MFC应用程序概述
全局函数
AfxAbort( ), 无条件中断应用程序 AfxMessageBox( ), 显示一个消息框 AfxGetApp( ), 返回一个指向Project的 CWinApp Object的指针 AfxGetAppName( ), 返回应用程序的名 字,类型为一个指向字符串的指针 AfxGetMainWnd( ), 返回指向主框架窗 口(Main Frame Window)的指针
可视化程序设计
第3章MFC应用程序概述
第3章 MFC应用程序概述
3.1 微软基础类MFC
MFC概述 MFC的类层次结构 MFC定义的宏、全局函数及全局变量 创建基于MFC框架的应用程序 MFC应用程序分析 消息的种类 消息映射及消息传递 自定义消息
3.2 MFC应用程序框架
ຫໍສະໝຸດ 3.3 消息机制
微软基础类MFC
类库是一个可以在应用程序中使用的相 互关联的类的集合。MFC中包含了200 多个类,封装了Windows的大部分编程 对象和相关的操作。MFC是一个庞大的 文件库,它由几百个执行文件和源文件 构成。
MFC的类层次结构
CObject
CWinThread
CCmdTarget
p B aseM ap _ m essag eE n tries[] lp E n tries n M essag e, n C o d e, n ID , n L astID , n S ig , p fn m essag eM ap
自定义消息
首先定义一个消息 #define WM_MYMESSAGE WM_USER+100 在.CPP文件的BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间定义一 个映射函数: ON_MESSAGE(WM_MYMESSAGE OnMyFn) 在相应的.h文件中定义函数 afx_msg LRSULT OnMyFn(WPARAM wParam,LPARAM lParam); 在相应的.h文件中定义函数 LRSULT CMyClass::OnMyFn(WPARAM wParam,LPARAM lParam){ …… return 0; }
MFC消息映像与消息路由网络构建及仿真
_ —
31 . 类别型 录仿真 网络构建 类别 型录网络记载 M C类库 中所有类的信息 ,包括类 的名称 , F 类 的大小 , 版本号 , 的创建 函数指 针及类的基类指针 。使用一个结构体 类 CR nie ls 表示 , ut Cas m 该结构体构成如下 :
Байду номын сангаас1 引言 .
信息化的发展 , 对软件开发提出了更高的要求。Mi oot C应用 c sfMF r 程序框架为程序员提供了高效的开发平台 , 但也隐藏了很多细节 。 消息 传递和路 由网络是一个典型的范例。下面构造仿真平台 , 构建消息映像 与消息路由网络 , 并给出 cnoe 真。 osl仿 2仿 真 平 台功 能模 块 . 微软定义了若干宏 , 完成 了对类别型 录的封装 , 形成 了一 张巨大的 类别型录网络(l s y e ew r) Ca p tok。图 1 出了几种技术 的关 系。Cas sT N 给 ls T e ew r 于技 术的 中枢位 置 , p N y tok处 在此基 础上 , 我们 可以完成运 行时 类型识别fT 1, R 1 )进而可以动态创建对象 (ya i rai )后 者又为数 D n mcC etn, o 据的永久存储(ess ne提供 了可 能。Widw 借助 于消息映像( s P r t c) ie nos Me— sg p ig构造 出消息映像表与消息映像链 。消息路 由( esg ot ae pn) Ma M sae u— R ig描 述 了消 息 在 各 个 对 象 之 间 的 流 动路 径 。 本 文 首 先 给 出 MF n) C型 录 网络 的构 建 过程 , 后 完 成 Mesg p ig和 Mes eR uig的 软 件 然 saeMapn sa o t g n 仿真 。
MFC消息映射机制剖析
一,消息映射机制1,消息响应函数:(例:在CDrawView类响应鼠标左键按下消息)1)在头文件(DrawView.h)中声明消息响应函数原型。
//{{AFX_MSG(CDrawView) //注释宏afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//}}AFX_MSG //注释宏说明:在注释宏之间的声明在VC中灰色显示。
afx_msg宏表示声明的是一个消息响应函数。
2)在源文件(DrawView.cpp)中进行消息映射。
BEGIN_MESSAGE_MAP(CDrawView, CView)//{{AFX_MSG_MAP(CDrawView)ON_WM_LBUTTONDOWN()//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()说明:在宏BEGIN_MESSAGE_MAP()与END_MESSAGE_MAP()之间进行消息映射。
宏ON_WM_LBUTTONDOWN()把消息WM_LBUTTONDOWN与它的响应函数OnLButtonDown ()相关联。
这样一旦有消息的产生,就会自动调用相关联的消息响应函数去处理。
宏ON_WM_LBUTTONDOWN()定义如下:#define ON_WM_LBUTTONDOWN() \{ WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp, \(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT,CPoint))&OnLButtonDown },3)源文件中进行消息响应函数处理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
菜单: 工具栏: 加速键: 按钮 注意:每个命令都是由一个 16 位的 ID 号码来标识的,命令的 ID 号码就是命令发送者 的 ID 号码,所有,具有相同 ID 号码的两个发送者,产生相同的命令。不同的 ID 号码值域 表示不同的命令类型,比如 0x8000<=ID<0xFFFF 范围的标志可以传递全局的命令,即命令可 以由不同的对象处理,菜单、工具栏、加速键默认为全局命令;按钮默认为局部命令,其 ID 小于 0x8000,这样按钮命令默认情况下只能在父窗口中进行处理。但是通过修改命令的 ID 值,也可以进行全局处理。命令消息的处理对象范围广泛,不仅在窗口类可以进行处理、而 且文档类、文档模版类和应用程序类都可以用来处理命令消息。 通知消息: 通知消息是指 Windows 窗口中的控件或者子窗口发送给其父窗的通知消息,有三种类 型的消息: (1) 第一种形式 Message=WM_COMMAND,lParam=控件窗口的句柄,HIGHWORD(wParam)=消息的 通知代码,LOWWORD(wParam)=表示控件的 ID
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) END_MESSAGE_MAP()
Windows 消息映射宏展开:
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode;
// control code or WM_NOTIFY code
在 Win3.x 中的控件的通用的通知消息宏定义 #define ON_CONTROL(wNotifyCode,id,memberFxn)\ {WM_COMMAND,(WORD)wNotifyCode,(WORD)id,id, AfxSig_vv,(AFX_PMSG)&memberFxn}, 编译控件的变更通知消息 #define ON_EN_CHANGE(id,memberFxn)\ ON_CONTROL(EN_CHANGE,id,memberFxn) MFC 为控件的每个通知消息都定义了宏
DECLARE_MESSAGE_MAP() }; (2) 在类的实现文件(.cpp)加上消息映射表格 BEGIN_MESSAGE_MAP(CTest5App, CWinApp)
//{{AFX_MSG_MAP(CTest5App) ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
#define ON_MESSAGE(message,memberFxn)\ {message,0,0,0,AfxSig_lwl,\ (AFX_PMSG)(AFX_PMSGW)(LRESULT(AFX_MSG_CALL CWnd::*)(WPARAM,LPARAM))&memberFxn},
#define ON_COMMAND(id,memberFxn)\ {WM_COMMAND,CN_COMMAND,(WORD)id,(WORD)id,AfxSig_vv,(AFX_PMSG)& memberFxn},
#else #endif
#define END_MESSAGE_MAP() \ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \ 一些典型的映射条目: #define ON_WM_PAINT()\ {WM_PAINT,0,0,0,AfxSig_vv,\ (AFX_PMSG)(AFX_PMSGW)(void(AFX_MSG_CALL CWnd::*)(void)&OnPaint),
反射消息 (1) 所 有 通 过 WM_COMMAND 发 送 的 通 知 消 息 , 其 反 射 消 息 的 定 义
为:ON_CONTROL_REFLECT(wNotifyCode,memberFxn) 例如:ON_CONTROL_REFLECT(EN_CHANGE, OnChange) (2) WM_NOTIFY 的反射消息定义是:ON_NOTIFY_REFLECT(wNotifyCode,memberFxn) (3) 特 殊 通 知 消 息 的 反 射 消 息 , 遵 守 一 定 的 命 名 规 则:ON_WM_CTLCOLOR-- ON_WM_COLOR_FEFLECT() 例如:ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
windows 消息处理函数: 消息处理函数都是类的成员函数。要对一个消息进行处理,就要定义该消息的处理函数。
在类中,增加一个消息处理函数包括一下三个内容: (1) 在类的定义中加入消息处理成员函数的函数原型(以 afx_msg) (2) 在类的消息映射表格中增加相应的消息入口项目 (3) 在类的实现中加入消息处理成员函数的函数体
(3) 第三种形式 Message=WM_NOTIFY wParam=控件的 ID,lParam=NMHDR 的指针 typedef struct tagNMHDR { HWND hwndFrom; // handle of control sending message UINT idFrom;// identifier of control sending message UINT code; // notification code; see below } NMHDR;
const AFX_MSGMAP* theClass::GetMessageMap() const \ { return &theClass::messageMap; } \
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \ { &theClass::_GetBaseMessageMap, &theClass::_messageEntries[0] }; \ AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \ {\
AFX_PMSG pfn; // routine to call (or special value)
};
struct AFX_MSGMAP
{
#ifdef _AFXDLL
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
#else
const AFX_MSGMAP* pBaseMap;
(2) 第二种形式 Message=具体的消息,wParam,lParam 根据消息的不同而不同。 在 Win3.1 中,通知消息无法传递附加的信息,但是一些通知消息如果不传递附加信息就没有意义, 对于这类通知消息,MFC 将他们定义成为特殊的处理函数,传送特定的参数,这类消息主 要 有 WM_CTLCOLOR 、 WM_VSCROLL 、 WM_HSCROLL 、 WM_DRAWITEM 、 WM_MEASUREITEM 、 WM_COMPAREITEM、WM_DELETEITEM、WM_CHARTOITEM、WM_VKEYTOITEM、WM_PARENTNOTOFY
消息处理的位置 Windows 消息映射:
在 MFC 中对消息的映射处理采用的是消息映射机制,消息映射机制就是消息及其处理函 数的一一对应表格以及分析和处理这张表格的应用程序框架内部的一些程序代码。凡是从 CcmdTarget 类派生的类都可以有消息映射,消息映射主要包含了如下两个方面的内容: (1) 在类的定义中(.h)加上一行宏调用: class CTest5App : public CWinApp { ….
UINT nID;
// control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig;
// signature type (action) or pointer to message #
#else #endif
#ifdef _AFXDLL #define BEGIN_MESSAGE_MAP(theClass, baseClass) \
const AFX_MSGMAP* PASCAL theClass::_GetBaseMessageMap() \ { return &baseClass::messageMap; } \
#endif
const AFX_MSGMAP_ENTRY* lpEntries;
};
#ifdef _AFXDLL
#define DECLARE_MESSAGE_MAP() \
private: \
static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
注意:ON_CONTROL 与 ON_COMMAND 的区别仅仅在于通知代码 #define ON_NOTIFY(wNotifyCode,id,memberFxn)\ {WM_NOTIFY,(WORD)wNotifyCode,(WORD)id,(WORD)id, \AfxSig_vNMHDRpl,(AFX_PMSG)(void(AFX_MSG_CALL CcmdTarget::*)(NMHDR*,LRESULT*))&memberFxn},
说扩展性不好 (4) 使用虚函数进行消息处理缺陷 3:控制的通知消息也是不可预知的, (5) 处理不可预知的命令和控制通知消息消息,只能采用繁琐的 Switch-case 语句 (6) 因此 MFC 没有采用虚函数机制,而是创造了消息映射机制 Windows 消息的分类: 窗口消息: