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为了让命令消息找到"最合适"的处理者而设计的一套传递规则。

相关推荐
阿豪只会阿巴6 小时前
【多喝热水系列】从零开始的ROS2之旅——Day4
c++·笔记·python·ros2
郭涤生7 小时前
fmtlib/fmt仓库熟悉
c++
Stanford_11067 小时前
【2026新年启程】学习之路,探索之路,技术之路,成长之路……都与你同行!!!
前端·c++·学习·微信小程序·排序算法·微信开放平台
郝学胜-神的一滴7 小时前
Linux线程属性设置分离技术详解
linux·服务器·数据结构·c++·程序人生·算法
w-w0w-w8 小时前
C++构造函数初始化列表全解析
c++
梵尔纳多8 小时前
初识 OpenGL
c++·图形渲染
王老师青少年编程8 小时前
2025年12月GESP(C++二级): 黄金格
c++·算法·gesp·csp·信奥赛·二级·黄金格
一起搞IT吧8 小时前
相机Camera日志实例分析之十二:相机Camx【萌拍后置zoom拍照】单帧流程日志详解
android·c++·数码相机·智能手机
十五年专注C++开发8 小时前
浅谈Qt中的QSql模块整体设计
开发语言·数据库·c++·qt
k***92168 小时前
C++:继承
java·数据库·c++