深入浅出MFC学习笔记(第三章:MFC六大关键技术之仿真:消息映射)

消息映射机制

SDK编程中,一般处理消息的方法就是使用switch/case判断消息的类型,然后进行响应。更模块化的方法是使用第一章介绍的消息映射表的方法,把消息和消息处理函数关联起来。

应该为每个需要处理消息的类构建一个消息映射表,并将基类与派生类的消息映射表连接起来。当窗口函数比较消息时,就沿着这条继承路线传递下去。为了实现这个目的我们仍然使用两个宏,完成这个功能复杂的构建。

首先定义一个数据结构:

//消息映射表元素类型。

structAFX_MSGMAP_ENTRY

{

UINTnMessage;

UINTnCode;

UINTnID;

UINTnLastID;

UINTnSig;

AFX_PMSGpfn;

};

structAFX_MSGMAP

{

AFX_MSGMAP*pBaseMessageMap;//指向基类的本结构。

AFX_MSGMAP_ENTRY*lpEntries;//本类的消息映射表。

};

在定义一个宏:

defineDECLARE_MESSAGE_MAP\

staticAFX_MSGMAP_ENTRY_messageEntries[];\

staticAFX_MSGMAPmessageMap;\

virtualAFX_MSGMAP*GetMessageMap()const;

该宏相当于在类中声明两个static数据成员和一个虚成员函数。

它们的定义由以下三个宏实现:

#defineBEGIN_MESSAGE_MAP(class_name,base_class)\

AFX_MSGMAP*class_name::GetMessageMap()const\

{return&class_name::message;}\

AFX_MSGMAPmessageMap=\

{&base_class::messageMap,class_name::_messageEntries}\

AFX_MSGMAP_ENTRY_messageEntries[]=\

{

#defineON_COMMAND(id,memFunc)\

WM_COMMAND,0,id,id,AFx_sig_vv\

,(AFX_PMSG)memFunc},\

#defineEND_MESSAGE_MAP()\

{0,0,0,0,AfxSig_end,(AFX_PMSG)0}\

CView为例,下面的代码:

classCWnd:publicCWnd

{

public:

DECLARE_MESSAGE_MAP()

};

BEGIN_MESSAGE_MAP(CView,CWnd)

ON_COMMAND(CViewid,0)

END_MESSAGE_MAP()

展开后变为:

classCView:publicCWnd

{

public:

staticAFX_MESSAGE_ENTRY_messageEntries[];

staticAFX_MSGMAPmessageMap;

virtualAFX_MSGMAP*GetMessageMap()const;

};

AFX_MSGMAP*CView::GetMessageMap()const

{

return&CView::messagemMap;

}

AFX_MSGMAPCView::messageMap=

{

&(CWnd::messageMap),

(AFX_MSGMAP_ENTRY*)&(CView::_messageEntries)

};

AFX_MSGMAP_ENTRYCView::_messageEntries[]=

{

{WM_COMMAND,0,122,122,1,(AFX_PMSG)0},

{0,0,0,0,0,(AFX_PMSG)0}

}

为了验证整个消息映射表,我们在每个类的消息映射表中添加了一个空的消息,这是为了做点标记,用于标示消息映射表的最后一个消息。MFC当然不是这样实现的。

/*CCmdTarget是消息传递的终点,因此在实现时需要特殊处理,这一点容易出错,要特别注意。

classCCmdTarget:publicCObject

{

DECLARE_DYNCREATE(CCmdTarget)

DECLARE_MESSAGE_MAP()

public:

CCmdTarget()

{

//cout<<"CCmdTargetconstructor!"<<endl;

//CreateObject();

}

~CCmdTarget()

{

//cout<<"CCmdTargetdestructor!"<<endl;

}

public:

};

IMPLEMENT_DYNCREATE(CCmdTarget,CObject)

AFX_MSGMAPCCmdTarget::messageMap=

{NULL,CCmdTarget::_messageEntries};

AFX_MSGMAP_ENTRYCCmdTarget::_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; }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值