MFC消息映射
来源:互联网 发布:两心之外无人知歌词 编辑:程序博客网 时间:2024/06/06 00:49
突然间想起这个是因为最近看到了AFX_MSGMAP_ENTRY这个结构,结果愣了半天,于是乎干脆又将这一块的相关知识看了一遍,哎,人上了岁数记忆就不行,需要写点东西帮忙记录一下自己的学习历程,不提这个,跑题了:
提起MFC消息,到底程序在哪里处理消息的,因为MFC对windows程序的很多地方进行了封装,导致入口地方不是那么容易找到,不过其实无非就是封装而已——CWinApp(应用程序),在MFC类窗口CxxxApp中查看基类就能找到,调试一下就会发现MFC程序执行的大致流程是:
CWinApp------>AfxWinMain(AfxGetApp,AfxInit)------>CWinApp::InitApplication------>CWinApp::InitINstance(Create)------>PreCreateWindow------>CWnd::ShowWindow,CWnd::UpdateWindow
AfxWinMain------>CWinApp::Run------>AfxInternalPumpMessage
Run这个函数来创建和处理消息循环
BOOL AFXAPI AfxInternalPumpMessage() { MSG msg; ::GetMessage(&msg, NULL, NULL, NULL); if (!AfxPreTranslateMessage(&msg)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return TRUE; }</span></span>
显而易见,MFC中处理消息也是利用了win32下的消息处理
那么还是这样的结构:
typedef struct tagMSG { HWND hwnd; UINT message; //消息的类型(即事件的类型) WPARAM wParam; //附加或称数据参数1 LPARAM lParam; DWORD time; POINT pt; } MSG; </span>
有了这个概念之后我们知道,MFC通过消息映射机制来派发或处理各种消息,关于消息映射,我去偷张图片过来:
没有高清无码大图,只能凑合着看了,关于上图可以这样理解:
子窗口在处理消息时需要用FUN1与是在自己的表中找到了,可是要用FUN100的时候,就找不到了,然后通过ParentTable到父类中MsgHandles找,找不到了,那就调用DefWindowProc默认处理了。
而MFC在实现这一过程中,需要去构建这个表,我们经常看到这样的代码,刚开始只是知道这个由vs自动生成,可是并不知道为什么
BEGIN_MESSAGE_MAP(CexampleDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON()END_MESSAGE_MAP()
我们来详细讲讲这个地方:
转到定义:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \ PTM_WARNING_DISABLE \ const AFX_MSGMAP* theClass::GetMessageMap() const \ { return GetThisMessageMap(); } \ const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \ { \ typedef theClass ThisClass; \ typedef baseClass TheBaseClass; \ static const AFX_MSGMAP_ENTRY _messageEntries[] = \ {#define END_MESSAGE_MAP() \ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ }; \ static const AFX_MSGMAP messageMap = \ { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \ return &messageMap; \ } \ PTM_WARNING_RESTORE
上面代码实质上添加了_messageEntries和messageMap(这是构建消息映射的关键)
AFX_MSGMAP_ENTRY _messageEntries[]
这是一个AFX_MSGMAP_ENTRY 类型的数组变量,是一个静态成员变量,用来容纳类的消息映射条目。一个消息映射条目可以用AFX_MSGMAP_ENTRY结构来描述。
AFX_MSGMAP_ENTRY结构的定义如下:
struct AFX_MSGMAP_ENTRY{ UINT nMessage; // windows message UINT nCode; // control code or WM_NOTIFY code UINT nID; // control ID (or 0 for windows messages) UINT nLastID; // used for entries specifying a range of control id's UINT_PTR nSig; // signature type (action) or pointer to message # AFX_PMSG pfn; // routine to call (or special value)};
从上述结构可以看出,每条映射有两部分的内容:第一部分是关于消息ID的,包括前四个域;第二部分是关于消息对应的执行函数,包括后两个域。
在上述结构的六个域中,pfn是一个指向CCmdTarger成员函数的指针。函数指针的类型定义如下:
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
当使用一条或者多条消息映射条目初始化消息映射数组时,各种不同类型的消息函数都被转换成这样的类型:不接收参数,也不返回参数的类型。因为所有可以有消息映射的类都是从CCmdTarge派生的,所以可以实现这样的转换。
nSig是一个标识变量,用来标识不同原型的消息处理函数,每一个不同原型的消息处理函数对应一个不同的nSig。在消息分发时,MFC内部根据nSig把消息派发给对应的成员函数处理,实际上,就是根据nSig的值把pfn还原成相应类型的消息处理函数并执行它。
第二个成员变量的声明
AFX_MSGMAP messageMap;
这是一个AFX_MSGMAP类型的静态成员变量,从其类型名称和变量名称可以猜出,它是一个包含了消息映射信息的变量。的确,它把消息映射的信息(消息映射数组)和相关函数打包在一起,也就是说,得到了一个消息处理类的该变量,就得到了它全部的消息映射数据和功能。AFX_MSGMAP结构的定义如下:
struct AFX_MSGMAP{ const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)(); const AFX_MSGMAP_ENTRY* lpEntries;};
成员函数 GetMessageMap() 用来得到自身消息映射的函数。
有了上面的一个概念之后,应该很容易理解MFC在处理一个消息的时候,往_messageEntries里加入要处理的函数,然后通过messageMap就可以得到消息映射数组_messageEntries和基类的消息映射数组的地址了
回头看看MFC的消息映射机制,了然了,在处理消息的时候构建的那张表,
BEGIN_MESSAGE_MAP(CexampleDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON()END_MESSAGE_MAP()
第一个处理的消息是ON_WM_SYSCOMMAND(),处理消息函数(右击转到定义)OnSysCommand
建好消息映射表后,消息就会流向到指定的处理函数里。
差不多消息映射机制就回顾了这么多了,写的很乱,放元旦搁了好几天又开始写的,思路接不上了呃。
0 0
- MFC 消息映射(转载)
- MFC消息映射机制
- MFC深入浅出--消息映射
- MFC的消息映射
- MFC消息映射机制
- MFC消息映射定义
- mfc 消息映射 处理
- MFC消息映射机制
- 【MFC】消息映射宏
- MFC消息映射梳理
- MFC消息映射
- MFC消息映射宏
- MFC消息映射机制
- MFC中的消息映射
- MFC深入浅出--消息映射
- MFC中的消息映射
- MFC消息映射机制
- MFC消息映射机制
- c tool系列------用poll函数查询IMEI
- OpenCV——PS滤镜算法之 球面化 (凹陷效果)
- MYSQL 内部结构优化器(MySQL Internals Optimizer)
- css实现菜单内容变换
- Shell程序
- MFC消息映射
- .Net程序员玩转Android开发---(17)Handler用法
- hello.c-hell.ko
- Linux最大线程数限制及当前线程数查询
- Java递归实现全排列改进(一)---利用HashSet实现去重
- java.util.Queue用法
- 动态链接库和静态链接库
- JAVA多线程和并发基础面试问答
- VS2010 常用快捷键