MFC仿真

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::InitApplicationpApp->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框架会按预定的顺序将这个消息传递给一系列相关的对象,直到找到能处理它的对象为止。

一个典型的单文档程序命令绕行顺序是:

  1. 当前活动的视图(Active View)
  2. 与视图关联的文档(Document)
  3. 文档所属的文档模板(Document Template)
  4. 主框架窗口(Main Frame Window)
  5. 应用程序对象(Application Object)

这种设计的好处是,你可以将命令处理逻辑放在最合适的对象里。例如,一个"保存"命令的处理函数放在文档类中就很自然,而"关于"对话框的打开命令则更适合放在应用程序类中处理。

简单来说,命令绕行就是MFC为了让命令消息找到"最合适"的处理者而设计的一套传递规则。

的处理函数放在文档类中就很自然,而"关于"对话框的打开命令则更适合放在应用程序类中处理。

简单来说,命令绕行就是MFC为了让命令消息找到"最合适"的处理者而设计的一套传递规则。

相关推荐
老赵的博客4 小时前
c++ unqiue指针
java·jvm·c++
程序猿编码5 小时前
基于 Linux 内核模块的字符设备 FIFO 驱动设计与实现解析(C/C++代码实现)
linux·c语言·c++·内核模块·fifo·字符设备
怎么没有名字注册了啊5 小时前
MFC_Install_Create
c++·mfc
Wadli6 小时前
C++语法 | static静态|单例模式
开发语言·c++·单例模式
进击的_鹏6 小时前
【C++11】initializer_list列表初始化、右值引用和移动语义、可变参数模版等
开发语言·c++
tongsound6 小时前
igh ethercat 实时性测试
linux·c++
睡不醒的kun7 小时前
leetcode算法刷题的第三十四天
数据结构·c++·算法·leetcode·职场和发展·贪心算法·动态规划
晚云与城7 小时前
今日分享:C++ deque与priority_queue
开发语言·c++
lingran__7 小时前
速通ACM省铜第四天 赋源码(G-C-D, Unlucky!)
c++·算法