1. MFC初始化的过程
通过全局变量theApp对象(为CMyWinApp类型)创建CMyFrameWnd完成建立窗口。可惜的是仿真中没有delete CMyFrameWnd对象。应该通过虚析构函数delete对象。
2.RTTI功能
为了能够达到RTTI,设计一个CRunTimeClass用于保存一些信息(类名、基类信息、函数指针-动态创建对象使用、模式等)。
设计两类宏,一类宏是在类的声明中使用,主要是给类增加一些成员(数据成员和成员函数)。为RTTI,主要增加一个静态的CRunTimeClass数据成员和一个虚成员函数(GetRunTimeClass),如:
#define DECLARE_DYNAMIC(class_name) /
public: /
static CRuntimeClass class##class_name; /
virtual CRuntimeClass* GetRuntimeClass() const;
第二类宏就是为上面增加的声明增加定义。如:
#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL) /
static char _lpsz##class_name[] = #class_name;/
CRunTimeClass class_name::class##class_name = { /
_lpsz##class_name,sizeof(class_name), wSchema, pfnNew, /
RUNTIME_CLASS(base_class_name), NULL }; /
//注:为了把各个类穿起来,使用下面的宏建立链表
static AFX_CLASSINIT _init_##class_name (&class_name::class##class_name); /
CRuntimeClass* class_name::GetRuntimeClass() const /
{ return &class_name::class##class_name; }
那么我们就可以在根据链表中CRunTimeClass进行RTTI识别了。
3.动态创建
刚才的CRunTimeClass里面有一个函数指针,而且CRunTimeClass对象为静态,因此修改原来的宏为原来类的定义中增加一个静态的CreateObject成员函数,并且在实现宏中让该静态函数和函数指针关联起来。静态的CreatObject成员函数可以new出一个对象并返回,那么我们根据遍历整个CRunTimeClass对象链表,调用对象的函数指针达到动态创建对象。
同样,遗憾的是仿真中没有处理delete动态创建的对象。
4.永久保存(Persistence)
这里的永久保存是站在Application Framework的角度来说的。即保存一些数据,框架通过读这些数据能够自动把原本的对象重构出来。
这里也是通过两类宏实现的。这两类宏分别是在类中增加operator>>友元函数(把数据串行化到文件中)的声明和定义。
5.消息映射
同样是通过宏的操作完成。主要是把消息和处理程序关联起来。定义如下:
enum AfxSig
{
AfxSig_end = 0, // [marks end of message map]
AfxSig_vv,
};
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;
增加的定义
#define BEGIN_MESSAGE_MAP(theClass, baseClass) /
AFX_MSGMAP* theClass::GetMessageMap() const /
{ return &theClass::messageMap; } /
AFX_MSGMAP theClass::messageMap = /
{ &(baseClass::messageMap), /
(AFX_MSGMAP_ENTRY*) &(theClass::_messageEntries) }; /
AFX_MSGMAP_ENTRY theClass::_messageEntries[] = /
{
//这个只是一个仿真,MFC是把处理消息的函数邦定。
#define ON_COMMAND(id, memberFxn) /
{WM_COMMAND, 0, (Word)id, (Word)id,AfxSig_vv, (AFX_MSG)memberFxn }
#define END_MESSAGE_MAP() /
{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } /
};
那么只需要在处理消息的类中使用宏定义就可以了。
6.消息传递
在MFC的消息不仅仅是在派生类和基类之间流动,还可以在同一层次之间流动。如。对于WM_COMMAND来说,消息处理的顺序可以整理为:Frame窗口先接受到消息,依次判断View、Frame窗口本身、CWinApp的DefWndProc是否处理,如果View要处理消息他也会依次判断View本身处理还是Document处理,如果是Document处理他也会依次判断Document本事处理还是Document Template处理。
因为上面类的层次关系。对于消息的传递只能通过静态、全局函数/虚函数来完成。
MFC的初始化和消息传递是需要OS支持的,并不需要用户干预,所以这些内容大多不会以宏来定义。剩下的四个专题都会和用户的具体需求相关,因此要求用户通过简单的宏完成代码的添加。