深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:消息映射)
2012-06-05 21:04
429 查看
消息映射机制
SDK编程中,一般处理消息的方法就是使用switch/case判断消息的类型,然后进行响应。更模块化的方法是使用第一章介绍的消息映射表的方法,把消息和消息处理函数关联起来。应该为每个需要处理消息的类构建一个消息映射表,并将基类与派生类的消息映射表连接起来。当窗口函数比较消息时,就沿着这条继承路线传递下去。 为了实现这个目的我们仍然使用两个宏,完成这个功能复杂的构建。
首先定义一个数据结构:
//消息映射表元素类型。
struct AFX_MSGMAP_ENTRY
{
UINT nMessage;
UINT nCode;
UINT nID;
UINT nLastID;
UINT nSig;
AFX_PMSG pfn;
};
struct AFX_MSGMAP
{
AFX_MSGMAP *pBaseMessageMap;//指向基类的本结构。
AFX_MSGMAP_ENTRY*lpEntries;//本类的消息映射表。
};
在定义一个宏:
define DECLARE_MESSAGE_MAP\
static AFX_MSGMAP_ENTRY _messageEntries[];\
static AFX_MSGMAP messageMap;\
virtual AFX_MSGMAP*GetMessageMap()const;
该宏相当于在类中声明两个static数据成员和一个虚成员函数。
它们的定义由以下三个宏实现:
#define BEGIN_MESSAGE_MAP(class_name,base_class)\
AFX_MSGMAP*class_name::GetMessageMap()const\
{return &class_name::message;}\
AFX_MSGMAP messageMap=\
{&base_class::messageMap,class_name::_messageEntries}\
AFX_MSGMAP_ENTRY _messageEntries[]=\
{
#define ON_COMMAND(id,memFunc)\
WM_COMMAND,0,id,id,AFx_sig_vv\
,(AFX_PMSG)memFunc },\
#define END_MESSAGE_MAP()\
{0,0,0,0,AfxSig_end,(AFX_PMSG)0}\
以CView为例,下面的代码:
class CWnd :public CWnd
{
public:
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CView,CWnd)
ON_COMMAND(CViewid,0)
END_MESSAGE_MAP()
展开后变为:
class CView :public CWnd
{
public:
static AFX_MESSAGE_ENTRY _messageEntries[];
static AFX_MSGMAP messageMap;
virtual AFX_MSGMAP*GetMessageMap()const;
};
AFX_MSGMAP*CView::GetMessageMap()const
{
return &CView::messagemMap;
}
AFX_MSGMAP CView::messageMap=
{
&(CWnd::messageMap),
(AFX_MSGMAP_ENTRY*)&(CView::_messageEntries)
};
AFX_MSGMAP_ENTRY CView::_messageEntries[]=
{
{WM_COMMAND,0,122,122,1,(AFX_PMSG)0},
{0,0,0,0,0,(AFX_PMSG)0}
}
为了验证整个消息映射表,我们在每个类的消息映射表中添加了一个空的消息,这是为了做点标记,用于标示消息映射表的最后一个消息。MFC当然不是这样实现的。
/* CCmdTarget是消息传递的终点,因此在实现时需要特殊处理,这一点容易出错,要特别注意。
class CCmdTarget:public CObject
{
DECLARE_DYNCREATE(CCmdTarget)
DECLARE_MESSAGE_MAP()
public:
CCmdTarget()
{
//cout<<"CCmdTarget constructor!"<<endl;
//CreateObject();
}
~CCmdTarget()
{
//cout<<"CCmdTarget destructor!"<<endl;
}
public:
};
IMPLEMENT_DYNCREATE(CCmdTarget,CObject)
AFX_MSGMAP CCmdTarget::messageMap=
{NULL,CCmdTarget::_messageEntries};
AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries[]=
{
{0,0,10,0,AfxSig_end,0},
{0,0,0,0,AfxSig_end,0}
};
AFX_MSGMAP*CCmdTarget::GetMessageMap()const
{
return &CCmdTarget::messageMap;
}
以下为包含动态创建、类型识别、消息映射的完整代码:
#include<iostream> #include<windows.h> #include<string> using namespace std; class CCmdTarget; typedef void (CCmdTarget::*AFX_PMSG)(void); //消息映射表元素类型。 enum AfxSig { AfxSig_end=0, AfxSig_vv, }; struct AFX_MSGMAP_ENTRY { UINT nMessage; UINT nCode; UINT nID; UINT nLastID; UINT nSig; AFX_PMSG pfn; }; struct AFX_MSGMAP { AFX_MSGMAP *pBaseMessageMap;//指向基类的本结构。 AFX_MSGMAP_ENTRY*lpEntries;//本类的消息映射表。 }; #define DECLARE_MESSAGE_MAP()\ public:\ static AFX_MSGMAP_ENTRY _messageEntries[];\ static AFX_MSGMAP messageMap;\ virtual AFX_MSGMAP*GetMessageMap()const;\ #define BEGIN_MESSAGE_MAP(class_name,base_class)\ AFX_MSGMAP*class_name::GetMessageMap()const\ {return &class_name::messageMap;}\ AFX_MSGMAP class_name::messageMap={&base_class::messageMap,class_name::_messageEntries};\ AFX_MSGMAP_ENTRY class_name::_messageEntries[]=\ { #define ON_COMMAND(id,memFunc)\ {WM_COMMAND,0,id,id,AfxSig_vv,(AFX_PMSG)memFunc },\ #define END_MESSAGE_MAP()\ {0,0,0,0,AfxSig_end,(AFX_PMSG)0}\ }; class CObject; class CRuntimeClass { public: char* m_lpszClassName;//对象所属类名 int m_nObjectSize;//对象大小 int m_wSchema;//模式号 CObject*(PASCAL*m_pfnCreateObject)();//构建函数,抽象类为NULL CRuntimeClass *m_pBaseClasss;//基类CRuntimeClass对象指针。 static CRuntimeClass *pFirstClass;//链表头指针。static CRuntimeClass *m_pNextClass;//下一指针。 public: CObject*CreateObject() { if(m_pfnCreateObject==NULL) { cout<<"该类型不支持动态创建!!"<<endl; return NULL; } CObject*pClass=(*m_pfnCreateObject)(); return pClass; } static CRuntimeClass*Load() { cout<<"请输入要动态创建的类名:"; string s; cin>>s; for(CRuntimeClass*pClass=pFirstClass;pClass;pClass=pClass->m_pBaseClasss) { if(pClass->m_lpszClassName==s) { return pClass; } } return NULL; } }; class AFX_CLASSINIT { public: AFX_CLASSINIT(CRuntimeClass*pNewClass)//构造函数 { pNewClass->m_pNextClass=CRuntimeClass::pFirstClass; CRuntimeClass::pFirstClass =pNewClass; } }; /************************************************************************/ /* 动态类型识别宏定义 //与CRuntimeClass类中的构建函数相区别。此处的CreateObject函数在每个类中都以static成员函数存在,用以 //初始化类型型录表,而CRuntimeClass中的CreateObject用于调用每个类的构建函数。仅仅是函数名相同罢了。*/ /************************************************************************/ #define DECLARE_DYNAMIC(class_name)\ public:\ static CRuntimeClass Class##class_name;\ virtual CRuntimeClass*GetRuntimeClass()const;\ #define DECLARE_DYNCREATE(class_name)\ DECLARE_DYNAMIC(class_name)\ static CObject*PASCAL CreateObject();\ #define RUNTIME_CLASS(class_name)\ (&class_name::Class##class_name)\ #define _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew)\ class CRuntimeClass class_name::Class##class_name ={\ #class_name,\ sizeof(class_name),wSchema,pfnNew,RUNTIME_CLASS(base_class_name),NULL};\ static AFX_CLASSINIT _init##class_name( RUNTIME_CLASS(class_name));\ CRuntimeClass *class_name::GetRuntimeClass()const\ {return &class_name::Class##class_name;}//此处将class_name写成了classname花了一两天才查出来。啊啊啊啊啊。20120605 #define IMPLEMENT_DYNAMIC(class_name,base_class_name)\ _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL)\ #define IMPLEMENT_DYNCREATE(class_name,base_class_name)\ CObject*PASCAL class_name::CreateObject(){return new class_name;}\ _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,class_name::CreateObject)\ /************************************************************************/ /* 对CObject特殊处理。 */ /************************************************************************/ class CObject { public: CObject() { //cout<<"CObject constructor!"<<endl; } ~CObject() { //cout<<"CObject destructor!"<<endl; } public: virtual CRuntimeClass*GetRuntimeClass(); static CRuntimeClass ClassCObject; public: bool IsKindOf(CRuntimeClass*pClass) { CRuntimeClass *pThis=GetRuntimeClass(); for(;pThis;pThis=pThis->m_pBaseClasss) { if(pThis==pClass) { return true; } } return false; } }; class CRuntimeClass CObject:: ClassCObject= { "CObject",sizeof(CObject),0xFFFF,NULL,NULL,NULL }; static AFX_CLASSINIT _init_CObject(&CObject:: ClassCObject); CRuntimeClass *CObject::GetRuntimeClass() { return &CObject::ClassCObject; } CRuntimeClass*CRuntimeClass::pFirstClass=NULL; /************************************************************************/ /* CCmdTarget是消息传递的终点,因此在实现时不能使用BEGIN_MESSAGE_MAP */ /************************************************************************/ class CCmdTarget:public CObject { DECLARE_DYNCREATE(CCmdTarget) DECLARE_MESSAGE_MAP() public: CCmdTarget() { //cout<<"CCmdTarget constructor!"<<endl; //CreateObject(); } ~CCmdTarget() { //cout<<"CCmdTarget destructor!"<<endl; } public: }; IMPLEMENT_DYNCREATE(CCmdTarget,CObject) AFX_MSGMAP CCmdTarget::messageMap= {NULL,CCmdTarget::_messageEntries}; AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries[]= { {0,0,10,0,AfxSig_end,0}, {0,0,0,0,AfxSig_end,0} }; AFX_MSGMAP*CCmdTarget::GetMessageMap()const { return &CCmdTarget::messageMap; } class CWnd:public CCmdTarget { DECLARE_DYNCREATE(CWnd) DECLARE_MESSAGE_MAP() public: CWnd() { //cout<<"CWnd constructor"<<endl; } ~CWnd() { //cout<<"CWnd destructor"<<endl; } public: virtual bool Create() { cout<<"CWnd::Create"<<endl; CreateEx(); return true; } bool CreateEx() { cout<<"CWnd::CreateEx"<<endl; PreCreateWindow(); return true; } virtual bool PreCreateWindow() { cout<<"CWnd::PreCreateWindow"<<endl; return true; } }; IMPLEMENT_DYNCREATE(CWnd,CCmdTarget) class CView :public CWnd { DECLARE_DYNCREATE(CView) DECLARE_MESSAGE_MAP() public: CView() { //cout<<"CView constructor"<<endl; } ~CView() { //cout<<"CView destructor"<<endl; } }; IMPLEMENT_DYNCREATE(CView,CWnd) class CFrameWnd:public CWnd { DECLARE_DYNCREATE(CFrameWnd) DECLARE_MESSAGE_MAP() public: CFrameWnd() { //cout<<"CFrameWnd constructor"<<endl; } ~CFrameWnd() { //cout<<"CFrameWnd destructor"<<endl; } public: virtual bool Create() { cout<<"CFrameWnd::Create"<<endl; CreateEx(); return true; } virtual bool PreCreateWindow() { cout<<"CFrameWnd::PreCreateWindow"<<endl; return true; } }; IMPLEMENT_DYNCREATE(CFrameWnd,CWnd) class CWinThread:public CCmdTarget { public: CWinThread() { //cout<<"CWinThread constructor"<<endl; } ~CWinThread() { //cout<<"CWinThread destructor"<<endl; } public: virtual bool InitInstance() { cout<<"CWinThread::InitInstance"<<endl; return true; } virtual bool Run() { cout<<"CWinThread::Run"<<endl; return true; } }; class CWinApp:public CWinThread { DECLARE_MESSAGE_MAP() public: CWinApp() { //cout<<"CWinApp Constructor "<<endl; m_currentApp=this; } ~CWinApp() { //cout<<"CWinApp destructor "<<endl; } virtual bool InitApplication() { cout<<"CWinApp::InitApplication"<<endl; return true; } virtual bool InitInstance() { cout<<"CWinApp:InitInstance"<<endl; return true; } virtual bool Run() { cout<<"CWinApp::Run"<<endl; return CWinThread::Run(); } public: CWinApp*m_currentApp; CFrameWnd*m_currentFrameWnd; }; class CDocument:public CCmdTarget { DECLARE_MESSAGE_MAP() public: CDocument() { //cout<<"CDocument constructor "<<endl; } ~CDocument() { //cout<<"CDocunment destructor "<<endl; } }; class CMyFrameWnd:public CFrameWnd { DECLARE_DYNCREATE(CMyFrameWnd) DECLARE_MESSAGE_MAP() public: CMyFrameWnd() { //cout<<"CMyFrameWnd constructor "<<endl; Create(); } ~CMyFrameWnd() { //cout<<"CMyFrameWnd destructor "<<endl; } }; IMPLEMENT_DYNCREATE(CMyFrameWnd,CFrameWnd) class CMyWinApp:public CWinApp { DECLARE_MESSAGE_MAP() public: CMyWinApp() { //cout<<"CMyWinApp constructor "<<endl; } ~CMyWinApp() { //cout<<"CMyWinApp destructor "<<endl; } public: bool InitInstance() { cout<<"CMyWinApp::InitInstance"<<endl; m_currentFrameWnd=new CMyFrameWnd; return true; } }; BEGIN_MESSAGE_MAP(CWnd,CCmdTarget) ON_COMMAND(1,0) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CFrameWnd,CWnd) ON_COMMAND(2,0) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CDocument,CCmdTarget) ON_COMMAND(3,0) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CView,CWnd) ON_COMMAND(4,0) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CWinApp,CCmdTarget) ON_COMMAND(5,0) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CMyWinApp,CWinApp) ON_COMMAND(6,0) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd) ON_COMMAND(7,0) END_MESSAGE_MAP() CMyWinApp myApp; CWinApp*AfxGetApp() { return myApp.m_currentApp; } void printAllMsgMapping(AFX_MSGMAP*p) { for(;p;p=p->pBaseMessageMap) { for(int i=0;p->lpEntries[i].nID;i++) { cout<<p->lpEntries[i].nID<<endl; } } } int main(int argc,char**argv) { CWinApp *pApp=AfxGetApp(); pApp->InitApplication(); pApp->InitInstance(); pApp->Run(); CRuntimeClass *pClass; CObject *pOb; cout<<"以下为类型型录链表中的所有类的名称:"<<endl; for(pClass=CRuntimeClass::pFirstClass;pClass;pClass=pClass->m_pBaseClasss) { cout<<pClass->m_lpszClassName<<endl; } CMyFrameWnd *pMyFrame=(CMyFrameWnd*)pApp->m_currentFrameWnd; printAllMsgMapping(pMyFrame->GetMessageMap()); cout<<endl; CDocument *pDoc=new CDocument; printAllMsgMapping(pDoc->GetMessageMap()); while(1) { pClass=CRuntimeClass::Load(); if(!pClass) { cout<<"找不到此类!!!"<<endl; } else { pOb=pClass->CreateObject(); if(pOb) { cout<<"创建成功!"<<endl; } } } return 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六大关键技术之(五)(六)——消息映射与命令传递
- 剖析MFC六大关键技术(五六)--消息映射与命令传递