MFC仿真
本文是《深入浅出MFC》第三章的读书笔记。
MFC类阶层

参考书中的源代码,不难发现main
函数中的pApp
就是指向theApp
的指针。
MFC类初始化过程

InitApplication
负责注册窗口类动作,InitInstance
负责创建窗口。通常,系统会(并且有能力)为你注册一些标准的窗口类别(当然也就准备好了一些标准的窗口函数),你(应用程序设计者)应该在你的CMyWinApp
中改写InitInstance
,并在其中把窗口产生出来,这样你才有机会在标准的窗口类别中指定自己的窗口标题和菜单。
因为CMyWinApp
类型的全局对象的存在,先初始化该对象,再执行main
函数。
cpp
//my.cpp
CMyWinApp theApp;
int main()
{
CWinApp* pApp = AfxGetApp();
pApp->InitApplication(); //注册窗口类
pApp->InitInstance(); //实例化窗口类
pApp->Run();
}
pApp->InitApplication()
调用的是CWinApp::InitApplication
,pApp->InitInstance()
调用的是CMyWinApp::InitInstance
(因为CMyWinApp
改写它了)。pApp->Run()
调用的是CWinApp::Run
。
RTTI
运行时类型识别,在程序运期间获得某个对象的具体类型信息。
类型链表
使用一个结构体CRuntimeClass
保存该类类的信息,并将该结构体作为类的一个成员。
使用DECLAER_DYNAMIC
宏,我们将CRuntimeClass
结构体放到类中,它执行的具体替换是定义一个类中静态的CRuntimeClass对象和声明一个获取该对象执政的虚函数。
使用IMPLEMENT_DYNAMIC
宏,我们将CRuntimeClass
结构体初始化并串联成链表。在该宏中,我们又使用了_IMPLEMENT_RUNTIMECLASS
宏,该宏用于初始化CRuntimeClass
。在该宏中,我们使用RUNTIME_CLASS宏生获取当前类的CRuntiemClass对象,AFX_CLASSINIT用于将新的类串联进链表中。
所有类的基类:CObject
不能使用DECLARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,应该手动初始化CRunTimeClass结构体并加入链表中。

IsKindOf
使用类型链表,我们可以定义一个函数判断一个类的类型。
在CObject中加上一个IsKindOf函数,使用该函数从参数传递的类开始,沿着父类CRunTimeClass的指针逐步判断。
动态生成
在程序执行期间,根据动态获得一个类的名称,要求程序产生一个对象。
有动态生成(Dynamic Creation)能力的类别库,必然亦拥有执行时期类型识别(RTTI)能力,因为_DYNCREATE 宏涵盖了_DYNAMIC宏。
在CRuntimeClass中使用函数指针指向一个类的成员函数,该成员函数返回一个该类的对象。CRuntimeClass中还有两个函数,一个用于调用函数指针,一个用于动态获得类型的名称,在链表中寻找该类的节点,找到后返回之。
永续生存机制(序列化)
把对象保存到文件中。把资料写到文件,很简单。在Document/View 架构中,资料都放在一份document(文件)里头,我们只要把其中的成员变量依续写进文件即可。成员变量很可能是个对象,而面对对象,我们首先应该记载其类别名称,然后才是对象中的资料。
DECLARE_SERIAL、IMPLEMENT_SERIAL宏用于重载>>操作符。
在CRuntimeClass中定义Store和Load函数,用于处理对象读写时的琐屑的工作。
消息映射
通过把消息和对应的消息处理函数封装在一起,并把这种结构体串联起来构成消息映射。
命令绕行
MFC中的命令绕行(Command Routing) 是一种让多个对象有机会处理同一命令消息(如菜单项或工具栏按钮触发)的机制。
当用户触发一个命令(比如点击菜单项),产生的 WM_COMMAND
消息不会仅由接收到它的最初窗口处理。MFC框架会按预定的顺序将这个消息传递给一系列相关的对象,直到找到能处理它的对象为止。
一个典型的单文档程序命令绕行顺序是:
- 当前活动的视图(Active View)
- 与视图关联的文档(Document)
- 文档所属的文档模板(Document Template)
- 主框架窗口(Main Frame Window)
- 应用程序对象(Application Object)
这种设计的好处是,你可以将命令处理逻辑放在最合适的对象里。例如,一个"保存"命令的处理函数放在文档类中就很自然,而"关于"对话框的打开命令则更适合放在应用程序类中处理。
简单来说,命令绕行就是MFC为了让命令消息找到"最合适"的处理者而设计的一套传递规则。
的处理函数放在文档类中就很自然,而"关于"对话框的打开命令则更适合放在应用程序类中处理。
简单来说,命令绕行就是MFC为了让命令消息找到"最合适"的处理者而设计的一套传递规则。