消息映射机制SDK编程中,一般处理消息的方法就是使用switch/case判断消息的类型,然后进行响应。更模块化的方法是使用第一章介绍的消息映射表的方法,把消息和消息处理函数关联起来。 应该为每个需要处理消息的类构建一个消息映射表,并将基类与派生类的消息映射表连接起来。当窗口函数比较消息时,就沿着这条继承路线传递下去。 为了实现这个目的我们仍然使用两个宏,完成这个功能复杂的构建。 首先定义一个数据结构: //消息映射表元素类型。 struct AFX_MSGMAP_ENTRY {
};
struct AFX_MSGMAP {
}; 在定义一个宏: define DECLARE_MESSAGE_MAP\
该宏相当于在类中声明两个static数据成员和一个虚成员函数。 它们的定义由以下三个宏实现: #define BEGIN_MESSAGE_MAP(class_name,base_class)\
#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()
};
展开后变为: class CView :public CWnd { public:
};
AFX_MSGMAP*CView::GetMessageMap()const {
} AFX_MSGMAP CView::messageMap= {
}; AFX_MSGMAP_ENTRY CView::_messageEntries[]= {
} 为了验证整个消息映射表,我们在每个类的消息映射表中添加了一个空的消息,这是为了做点标记,用于标示消息映射表的最后一个消息。MFC当然不是这样实现的。 /* CCmdTarget是消息传递的终点,因此在实现时需要特殊处理,这一点容易出错,要特别注意。 class CCmdTarget:public CObject {
public:
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; }
原文链接:http://blog.csdn.net/ithzhang/article/details/7635945 |
|