第3节 MFC六大关键技术
MFC所有的封装类一共有200多个,但是MFC的内部技术不只是简单的封装。MFC的内部总共有六大黑箱技术架构起整个MFC的开发平台。六大关键技术的目的是为了提高开发效率,开发者只要在局部作简单的修改,即可处理大部分窗口事务。MFC的六大关键技术包括MFC程序的初始化过程、运行时类型识别(RTTI)、动态创建、永久保存、消息映射和消息传递。
下面新建一个Win32程序,手动升级到MFC程序,演示“MFC初始化过程”的原理。
1)执行File→New命令或按快捷键<Ctrl+N>,弹出新建对话框,如图3-14所示。

图3-14 建立Win32应用程序
选中“Win32 Application”列表项,选择工程目录后填写工程名称“MFC32”。
2)单击“OK”按钮后进入应用程序,选中“A simple Win32 application”,如图3-15所示。

图3-15 Win32应用程序向导
3)单击“Finish”按钮完成创建工程后,在类视图中双击WinMain函数并修改代码,如图3-16所示。

图3-16 编写CWinApp派生类
4)按<F7>键编译代码,输出窗口中的错误提示,如图3-17所示。

图3-17 基类未定义错误
5)错误原因是没有包含CWinApp类所在的头文件。
在FileView中双击“StdAfx.h”,去掉Win32头文件并添加MFC头文件,如图3-18所示。
6)再次按<F7>键编译代码,错误提示如图3-19所示。
7)产生这个错误的原因是没有链接到MFC代码库。

图3-18 添加MFC头文件

图3-19 MFC链接错误(https://www.daowen.com)
执行Project→Settings命令或者按快捷键<Alt+F7>进行设置。在“Project Settings”对话框中选择“Use MFC in a Static Library”,然后单击“OK”按钮完成MFC链接设置,如图3-20所示。

图3-20 MFC类库链接设置
8)按<F7>键编译没有错误,运行生成的可执行文件测试代码,如图3-21所示。

图3-21 查看运行结果
9)CWinApp::InitInstance虚函数与WinMain函数的关系。
把光标停放在CMyApp类中的InitInstance函数处,按<F9>键设置断点,再按<F5>键让程序运行到断点处。从Variables的调试窗口的下拉列表中,可以看到MFC执行程序的启动过程。操作系统内核(kernel32.dll)先调用WinMain函数,在WinMain函数中再调用CWinApp派生类中的InitInstance函数,如图3-22所示。
10)在下拉列表中随意单击列表中的每个函数,都可以查看到对应的函数代码,如图3-23所示。

图3-22 在调试窗口中查看函数之间的调用关系

图3-23 MFC封装的启动过程代码
在AfxWinMain函数中,发现其中pThread和pApp都是指向theApp全局变量地址的指针变量。通过基类指针执行pThread→InitInstance()时,会自动回调到派生类中,因为该函数是虚函数。
11)任何应用程序启动的过程,都是从操作系统内核(kernel32.dll)调用可执行文件的主函数开始的。控制台或者DOS程序的主函数是main函数,而Windows程序的主函数是WinMain函数。MFC程序和Win32程序一样,都是由WinMain函数启动的,只不过MFC将WinMain函数封装起来了而已。对于初学者可以认为,CWinApp派生类中的InitInstance虚函数就是MFC程序的主函数。
12)不借助“MFC AppWizard”,手工建立MFC程序只需几个步骤。
①从CWinApp类派生一个应用程序类。
②使用派生类定义的全局变量(theApp)。
③在预定义头文件“stdafx.h”中禁用“windows.h”,取而代之是以afx开头的MFC头文件。
④编译设置中选择“Use MFC in a Static Library”。
⑤在CWinApp派生类中,重写InitInstance函数作为程序启动代码。