分享

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

 戴维图书馆 2014-05-11

 

消息映射机制

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;
}



原文链接:http://blog.csdn.net/ithzhang/article/details/7635945

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多