MFC六大关键技术之仿真学习笔记(七)
来源:互联网 发布:linux内核编译命令 编辑:程序博客网 时间:2024/05/22 07:02
从学习Windows的消息机制学习到MFC的消息映射,这是我最喜欢的一节。在Win32编程中,你回去定义各种消息,在WndProc中通过switch ..case..进行消息的分类处理。带着这种思维走进MFC,你会发现MFC采用一种消息映射表模式来简化消息处理。虽说书上理解起来很简单,关于消息如何在MFC框架中流动,其中原理是什么,这才是我们应该学会的,而不是仅仅学会如何使用。
*Message Mapping(消息映射)
当然我们希望消得以下流动
消息流动的终点在CCmdTarget,我们来看看消息如何实现以上的流动的,先来介绍两个数据结构:
typedef void (CCmdTarget::*AFX_PMSG)(void);struct AFX_MSGMAP_ENTRY{UINT nMessage;UINT nCode;UINT nID;UINT nLastID;UINT nSig;AFX_PMSG pfn;};即:定义一个AFX_MSGMAP_ENTRY,通过结构我们可以获得消息对应的处理函数指针。
struct AFX_MSGMAP{AFX_MSGMAP* pBaseMessageMap;AFX_MSGMAP_ENTRY* lpEntries;};即:通过AFX_MSGMAP,可以获得类成员的AFX_MSGMAP_ENTRY指针,从而获得类中所有消息映射,通过pBaseMessageMap获得基类的AFX_MSGMAP指针,这样可以实现"同宗"的流动。
同样,MFC也为了降低我们的工作量,构建了几个宏: DECLARE_MESSAGE_MAP,BEGIN_MESSAGE_MAP,END_MESSAGE_MAP。
来看看具体的定义:
#define DECLARE_MESSAGE_MAP() \static AFX_MSGMAP_ENTRY _messageEntries[]; \static AFX_MSGMAP messageMap; \virtual AFX_MSGMAP* GetMessageMap() const;即:还是老套路,声明static变量来保证每个类中静态成员唯一,_messageEntries[]保存了类的消息映射信息,messageMap是子类和父类消息映射的纽带,消息通过向上流动可以实现遍历。虚函数GetMessageMap() 返回类对应的messageMap。
如图:
#define BEGIN_MESSAGE_MAP(theClass,baseClass) \AFX_MSGMAP* theClass::GetMessageMap() const \{ return &theClass::messageMap; } \AFX_MSGMAP theClass::messageMap = { &(baseClass::messageMap),(AFX_MSGMAP_ENTRY *)&(theClass::messageEntries) };\AFX_MSGMAP_ENTRY theClass::messageEntries[] = \ { #define END_MESSAGE_MAP() \{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0} \ };即:BEGIN_MESSAGE_MAP与END_MESSAGE_MAP是成对出现的,看了宏定义确实如此,当然在实际代码中我们经常写到:
BEGIN_MESSAGE_MAP(CMyWinApp, CWinApp)ON_COMMAND(CMyWinAppid, 0)END_MESSAGE_MAP()在俩宏的中间加入了我们的消息映射,当然ON_COMMAND宏我们也可以自行实现,只需要实现宏完成一个_messageEntries的初始化。
#define ON_COMMAND(id, memberFxn) \{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \static_cast<AFX_PMSG> (memberFxn) },当然,我们对END_MESSAGE_MAP()中的AfxSig_end定义为:
enum AfxSig{AfxSig_end = 0, // [marks end of message map]}代表消息映射的结束。
当然,这两个宏怎么用呢,其实很简单,下面用CView作为Demo:
头文件:
class CView :public CWnd{public:CView(){std::cout << "CView Constructor \n";}~CView(){std::cout << "CView Destructor \n";}DECLARE_MESSAGE_MAP()};Cpp文件:
BEGIN_MESSAGE_MAP(CMyView, CView)ON_COMMAND(CMyViewid, 0)END_MESSAGE_MAP()
我们在main函数中测试一下:
void printlpEntries(AFX_MSGMAP_ENTRY *lpEntry){struct{int classid;char* classname;}classinfo[] ={CCmdTargetid, "CCmdTarget",CWinThreadid, "CWinThread",CWinAppid, "CWinApp",CMyWinAppid, "CMyWinApp",CWndid, "CWnd",CFrameWndid, "CFrameWnd",CMyFrameWndid, "CMyFrameWnd",CViewid, "CView",CMyViewid, "CMyView",CDocumentid, "CDocument",CMyDocid, "CMyDoc",0, " "};for (int i = 0; classinfo[i].classid != 0; i++){if (classinfo[i].classid == lpEntry->nID){std::cout << lpEntry->nID << " ";std::cout << classinfo[i].classname << std::endl;break;}}}void MsgMapPrinting(AFX_MSGMAP * pMessageMap){for (; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMessageMap){AFX_MSGMAP_ENTRY * lpEntry = pMessageMap->lpEntries;printlpEntries(lpEntry);}}int _tmain(int argc, _TCHAR* argv[]){CWinApp * pApp = AfxGetApp();pApp->InitApplication();pApp->InitInstance();pApp->Run();CMyDoc *pMyDoc = new CMyDoc;CMyView *pMyView = new CMyView;CFrameWnd * pMyFrame = (CFrameWnd *)pApp->m_pMainWnd;AFX_MSGMAP *pMessageMap = pMyDoc->GetMessageMap();std::cout << std::endl << "MyDoc MessageMap : " << std::endl;MsgMapPrinting(pMessageMap);pMessageMap = pMyView->GetMessageMap();std::cout << std::endl << "MyView MessageMap : " << std::endl;MsgMapPrinting(pMessageMap);pMessageMap = pMyFrame->GetMessageMap();std::cout << std::endl << "MyFrame MessageMap : " << std::endl;MsgMapPrinting(pMessageMap);pMessageMap = pApp->GetMessageMap();std::cout << std::endl << "pApp MessageMap : " << std::endl;MsgMapPrinting(pMessageMap);system("pause");return 0;}
结果:
0 0
- MFC六大关键技术之仿真学习笔记(七)
- 三、MFC 六大关键技术之仿真 (学习笔记)
- MFC六大关键技术之仿真学习笔记(一)
- MFC六大关键技术之仿真学习笔记(二)
- MFC六大关键技术之仿真学习笔记(三)
- MFC六大关键技术之仿真学习笔记(四)
- MFC六大关键技术之仿真学习笔记(六)
- MFC六大关键技术之仿真学习笔记(五)
- MFC六大关键技术之仿真学习笔记(八)
- 深入浅出MFC学习笔记:(第三章MFC六大关键技术之仿真:类型识别,动态创建) .
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:消息映射)
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
- 深入浅出MFC学习笔记:(第三章MFC六大关键技术之仿真:类型识别,动态创建)
- 深入浅出MFC学习笔记:(第三章MFC六大关键技术之仿真:类型识别,动态创建) .
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:消息映射)
- 深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:命令传递) .
- MFC六大关键技术之仿真(一)
- 深入浅出MFC学习笔记:MFC六大关键技术仿真之MFC程序的初始化过程
- System memory,AGP memory和video memory
- Bootm命令
- java.lang.NoClassDefFoundError: com/opensymphony/xwork2/util/finder/DefaultClassFinder$InfoBuildingV
- mysql常用命令总结
- 【Bible for kids】 儿童圣经 App
- MFC六大关键技术之仿真学习笔记(七)
- Git深度使用经验总结
- php数组函数(3)
- cout.get() P494
- Shellcode的编写
- 在Win7系统中配置Eclipse的JDK环境变量
- linux下格式化分区和重新挂载的命令,适用于centos和redhat
- VS2010无法连接SQL SERVER2008
- apt-file 解决软件包依赖