消息映射机制
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;
}
分享到:
相关推荐
深入浅出MFC读书笔记3 深入浅出MFC 读书笔记
深入浅出MFC读书笔记2 深入浅出MFC 读书笔记
我个人特别喜欢第3章:MFC 六大关键技术之仿真。这章内容的设计的确在MFC 丛林中,大刀阔斧地披露出最重要的筋络,我相信这正是所有学习MFC 的人所需要的一种表明方式。对我而言,以往遗留的许多疑惑,在此都一一...
我个人特别喜欢第3章:MFC 六大关键技术之仿真。这章内容的设计的确在MFC 丛林中,大刀阔斧地披露出最重要的筋络,我相信这正是所有学习MFC 的人所需要的一种表明方式。对我而言,以往遗留的许多疑惑,在此都一一...
第三章 MFC六大关键技术之仿真 第二篇 欲善工事先利其器 第四章 Visual C++ 集成开发环境 第三篇 浅出MFC程序设计 第五章 总观Application Framework 第六章 MFC程序的生死因果 第七章 简单而完整:MFC骨干程序 第四...
第3章 mfc六大关键技术之仿真 第二篇 欲善工事先利其器 第4章 visual c++集成开发环境 第三篇 浅出mfc程序设计 第5章 总观application framework 第6章 mfc程序的生死因果 第7章 简单而完整:mfc骨干程序...
这是MFC的学习笔记,很好的。比较容易入门。
深入浅出MFC读书笔记 MFC 深入浅出
《深入浅出MFC》第三章MFC关键技术仿真 vs2013代码
深入浅出MFC 深入浅出MFC 深入浅出MFC
深入浅出MFC_简体中文版_侯捷 + 深入浅出MFC笔记(配合原书的好笔记)
《深入浅出MFC》分为四大篇。第一篇提出学习MFC程序设计之前的必要基础,包括Windows程序的基本观念以及C++的高阶议题。
《深入浅出MFC》读书心得,我多年的笔记。
深入浅出MFC--侯捷深入浅出MFC--侯捷深入浅出MFC--侯捷深入浅出MFC--侯捷深入浅出MFC--侯捷深入浅出MFC--侯捷深入浅出MFC--侯捷
第三章 MFC六大关键技术之仿真 第二篇 欲善工事先利其器 第四章 Visual C++ 集成开发环境 第三篇 浅出MFC程序设计 第五章 总观Application Framework 第六章 MFC程序的生死因果 第七章 简单而完整:MFC骨干程序 第四...
第3章 MFC六大关键技术之仿真 MFC类层次结构 Frame 1范例程序 MFC程序的初始化过程 Frame 2范例程序 RTTI(执行期类型识别) 类别型录网与CRuntimeClass DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏 Frame 3范例程序 Is...
深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf深入浅出MFC.pdf
第3章 MFC六大关键技术之仿真 MFC类层次结构 Frame 1范例程序 MFC程序的初始化过程 Frame 2范例程序 RTTI(执行期类型识别) 类别型录网与CRuntimeClass DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏 Frame 3范例程序 Is...
我个㆟特别喜欢第3章:MFC 六大关键技术之模拟。这章内容的设计的确在 MFC 丛林㆗, 大刀阔斧㆞披露出最重要的筋络,我相信这正是所有学习 MFC 的㆟所需要的㆒种表明方 式。对我而言,以往遗留的许多疑惑,在此都㆒...