MFC学习记录1
一、MFC六大关键技术
1、MFC初始化----寻找main函数
C++规定,全局对象的构造将比main或WinMain函数更早。
首先是全局构造
CObject构造函数 -> CCmdTarget -> CWinThread -> CWinApp -> theApp构造函数
然后进入WinMain函数
WinMain -> AfxWinMain -> AfxWinInit -> theApp.InitApplication -> theApp.InitInstance
接着执行线程过程。
theApp.Run()
最后清理
AfxWinTerm
2、执行时类型识别(RTTI)-- -- 查询父子关系(true or false)
CRuntimeClass的实现要通过几个复杂的宏DECLARE_DYNAMIX(Cxxx)和IMPLEMENT_DYNAMIC(Cxxx,Cxxxbase),在类内部声明这两个宏,就可以将该类加入到类型识别库。而CObject的函数IsKindOf()则可以指向任何派生至CObject的类,然后调用它就可以找到基类。
3、动态生成(Dynamic Creation) ----- 如何从文件中读取一个类并实现它
动态生成也通过CRuntimeClass来实现,加入两个成员变量,并通过宏来实现。DECLARE_DYNCREATE 和IMPLEMENT_DYNCREATE 。
4、永久保存(Persistence) -- -- 将对象写入到文件(Serialize)
这需要用到宏DECLARE_SERIAL / IMPLEMENT_SERIAL,以及CObject的虚函数 virtual void Serialize(CArchive& ar);
5 、消息映射(Message Mapping)---- 消息如何获取
宏DECLARE_MESSAGE_MAP / BEGIN_MESSAGE_MAP / END_MESSAGE_MAP
6、命令绕行(Command Routing)---- 消息流动方向
一般Window消息(WM_xxx),一定是从子类流向父类,不可能旁流。
命令消息WM_COMMAND 的消息流向比较另类,可以横向流动。
二、MFC生死因果
程序的诞生:
Application object 产生,内存于是获得配置,初值亦设立了。
Afx WinMain 执行AfxWinInit,后者又调用AfxInitThread,把消息队列尽量加大到96。
Afx WinMain 执行InitApplication。这是CWinApp 的虚拟函数,但我们通常不改写它。
AfxWinMain 执行InitInstance。这是CWinApp 的虚拟函数,我们必须改写它。
CMyWinApp::InitInstance 'new' 了一个CMyFrameWnd 对象。
CMyFrameWnd 构造式调用Create,产生主窗口。我们在Create 参数中指定的窗口类别是NULL, 于是MFC 根据窗口种类, 自行为我们注册一个名为"AfxFrameOrView42d" 的窗口类别。
回到InitInstance 中继续执行ShowWindow,显示窗口。
执行UpdateWindow,于是发出WM_PAINT。
回到AfxWinMain,执行Run,进入消息循环。
程序开始运作:
程序获得WM_PAINT 消息(藉由CWinApp::Run 中的::GetMessage 循环)。
WM_PAINT 经由::DispatchMessage 送到窗口函数CWnd::DefWindowProc 中。
CWnd::DefWindowProc 将消息绕行过消息映射表格(Message Map)。
绕行过程中发现有吻合项目,于是调用项目中对应的函数。此函数是应用程序利用BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 之间的宏设立起来的。
标准消息的处理例程亦有标准命名,例如WM_PAINT 必然由OnPaint 处理。程序的死亡:
使用者选按【File/Close】,于是发出WM_CLOSE。
CMyFrameWnd 并没有设置WM_CLOSE 处理例程,于是交给预设之处理例程。
预设函数对于WM_CLOSE 的处理方式是调用::DestroyWindow, 并因而发出WM_DESTROY。
预设之WM_DESTROY 处理方式是调用::PostQuitMessage,因此发出WM_QUIT。
CWinApp::Run 收到WM_QUIT 后会结束其内部之消息循环, 然后调用ExitInstance,这是CWinApp 的一个虚拟函数。
如果CMyWinApp 改写了ExitInstance , 那么CWinApp::Run 所调用的就是CMyWinApp::ExitInstance,否则就是CWinApp::ExitInstance。
最后回到AfxWinMain,执行AfxWinTerm,结束程序。
三、Document-View
1、Document
Document 在MFC 的CDocument 里头被具体化。CDocument 本身并无任何具体数据,它只是提供一个空壳。当你开发自己的程序,应该从CDocument 衍生出一个属于自己的Document 类别,并且在类别中声明一些成员变量,用以承载(容纳)数据。然后再(至少)改写专门负责文件读写动作的Serialize 函数。应为他派生至CObject,所有它有CObject 所支持的一切性质,包括执行时期型别信息(RTTI)、动态生成(Dynamic Creation)、文件读写(Serialization)。
2、View
View 负责描述Document中的资料,也是在在MFC 的CView 里头被具体化。它只是提供一个空壳。当你开发自己的程序,应该从CView 衍生出一个属于自己的View 类别,并且在类别中(至少)改写专门负责显示资料OnDraw 函数(针对屏幕)或OnPrint 函数(针对打印机)。由于CView 衍生自CWnd,所以它可以接收一般Windows 消息(如WM_SIZE、WM_PAINT 等等),又由于它也衍生自CCmdTarget,所以它可以接收来自菜单或工具列的WM_COMMAND 消息。
3、Frame
框架窗口在Document/View之上,主要管理UI。
4、 Document Template
MFC 把Document/View/Frame 视为三位一体。其中用 Document Template来管理这个"三人组合"。MFC 有一个CDocTemplate 负责管理。