创建单文档工程后vs将生成可以执行的代码框架,文档应用程序中,都有五个类,部分类名和工程名相关联。图1展示了IDE向导生成的代码结构示意图以及对应的类功能。
在MFC程序有且仅有一个从应用程序类(CWinApp)派生的类,而且仅有一个该派生类的实例化对象;我们发现该程序中确实存在一个theApp的全局变量,该全局变量就代表了这个应用程序本身;win32和MFC应用程序实例表示区别如下:
知识点:
1.Afx前缀的函数代表应用程序框架(Application Framework)函数,属于全局函数,它们可以在程序的任何地方被调用。
2.以域作用符“::”开始的表示的函数,表明该函数是一个全局函数。
MFC运行流程
现在直接给出MFC程序执行顺序,但着重分析其运行机制和功能分析,其流程是“theApp全局对象定义->TestApp构造函数->WinMain函数”。在执行
theApp对象的构造函数之前先执行CWinApp基类的构造函数,从而把我们自己创建的类和MFC类相关联起来了。
流程详解:
1.全局变量定义;程序入口函数WinMain加载时,系统先为全局对象分配内存空间,从而利用theApp完成应用程序的启动。
2.创建对象时会调用对象的构造函数;theApp是子类CTestApp是实例对象,子类继承于CWinApp,因此会先调用基类的构造函数,再调用子类的构造
函数,从而完成应用程序的初始化工作,例如基类中保存theApp的this指针。
3.进入WinMain函数;在AfxWinMain函数中可以获取子类的this指针,利用此指针调用InitApplication、InitInstance、Run等函数,从而完成窗口类的注
册,创建,消息循环、显示,更新。
4.进入消息循环,响应各种消息,直到退出;MFC程序实际上是采用消息映射机制,来完成各种消息的处理,收到WM_QUIT消息时,退出消息循环。
代码跟踪
下面将给出MFC运行过程的代码跟踪,主要列出MFC框架涉及到的主要函数以及所在的文件名,具体的代码流程可以自行debug跟踪,并利用调用栈完成函数跟踪。细致函数跟踪和分析,这不详细给出,代码跟踪,如图所示。相关的源码文件位置是:...\VC\atlmfc\src\mfc;
文档/视类结构
我们创建的MFC程序除了主框架窗口外,还有一个窗口就是视类窗口,对应的是CView类。框架窗口是视类窗口的一个父窗口,它们的关系如图4.红色包围的是主框架窗口,蓝色包围的是视窗口。微软在设计基础类库时,采用数据存储和数据显示分离的模式,数据存储由CDocument类完成,数据显示和修改由CView类完成。在CTestApp的Initstance方法中定义一个单文档模板对象指针,该对象就把文档类对象、框架类对象、视窗类对象有机地组织在一起,接着利用AddDocTemplate函数把这个单文档模板添加到文档模板中,从而把这个三个类组织成为一个整体,源码如下:
1 LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) 2 // 注册应用程序的文档模板。文档模板 3 // 将用作文档、框架窗口和视图之间的连接 4 CSingleDocTemplate* pDocTemplate; 5 pDocTemplate = new CSingleDocTemplate( 6 IDR_MAINFRAME, 7 RUNTIME_CLASS(CTestDoc), 8 RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口 9 RUNTIME_CLASS(CTestView)); 10 if (!pDocTemplate) 11 return FALSE; 12 AddDocTemplate(pDocTemplate); 13 14 LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) 15 16 // 注册应用程序的文档模板。文档模板 17 18 // 将用作文档、框架窗口和视图之间的连接 19 20 CSingleDocTemplate* pDocTemplate; 21 22 pDocTemplate = new CSingleDocTemplate( 23 24 IDR_MAINFRAME, 25 26 RUNTIME_CLASS(CTestDoc), 27 28 RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口 29 30 RUNTIME_CLASS(CTestView)); 31 32 if (!pDocTemplate) 33 34 return FALSE; 35 36 AddDocTemplate(pDocTemplate);
窗口类、窗口类对象和窗口
C++窗口类对象和窗口并不是一回事,它们之间唯一的关系式C++窗口类对象内部定义了一个窗口句柄变量,保存了与这个c++窗口类对象相关的那个窗口句柄。窗口销毁时,与之对应的c++窗口类对象销毁与否,要看其生命周期是否结束。但是c++窗口类对象销毁时,与之关联的窗口也将销毁。
MFC相关学习可以参考:
1. MFC源码实战分析
CObject--》CCmdTarget--》CWinThread—》CWinApp ------》initinstance()
CwinApp类:CObject->CCmdTarget->CWinThread->CWinApp->initinstance()