Lesson2:MFC框架程序剖析
微软基础类库MFC(Microsoft Foundation Class):是微软为简化程序而开发的一套C++类的集合,是一套面向对象的函数库,以类的方式提供给用户使用。MFC库是开发Windows程序的C++接口,MFC提供了面向对象的框架,开发人员基于这一框架开发Windows应用程序。MFC采用面向对象设计,将大部分WindowsAPI封装的C++的类中,以类成员函数的形式提供给开发人员使用。
1.一个典型的MFC单文档程序会自动生成一些类文件,包括下面几个类:
①CAboutDig类,表示对话框类,是帮助/关于窗口,这个可有可无
②CMainFrame类继承于CFrameWnd类,表示框架类窗口,一般是外面最大的那个窗口
③CXXXApp类继承于CWinApp类,表示了应用程序对象,一个程序有且仅有一个应用程序对象,程序从应用程序实例对象开始运行
④CXXXDoc类继承于CDocument类,表示文档类,数据的处理在此进行
⑤CXXXView类继承于CView类,表示视图类窗口,此窗口附在框架类窗口之上,一般是窗口中的白色区域,数据的显示在此进行
其中CFrameWnd和CView都继承于CWnd, CWnd类是MFC中一个非常重要的类,它封装了与窗口相关的操作。下面是MFC类的继承关系图。
2.MFC程序运行机制(过程)
参考文献:http://blog.sina.com.cn/s/blog_752af88e0100x17z.html
对于普通的VC++控制台程序,无论全局变量还是全局对象(类),程序运行时,在加载main函数之前,就已经为它们分配了内存空间。对于一个全局对象来说,此时就会调用该对象的构造函数,构造该对象,并进行初始化操作,如果是构造子类对象时,会自动调用父类的构造函数,此时在父类的构造函数中的this指针所指向的是子类对象地址。MFC程序具有一个CXXXApp类的全局对象theApp,这时this指针就可以指向这个全局对象,程序从这里开始进行,它就是应用程序对象,也就是上一讲Windows程序内部运行机制中所讲的应用程序的实例(HINSTANCE hInstance, // handle to current instance 当前运行实例句柄 )。在MFC程序运行时,程序执行的顺序为:theApp全局对象定义处->CXXXApp构造函数->WinMain函数->设计窗口->注册窗口->创建窗口->显示窗口->消息循环。
MFC程序的WinMain函数,在由Appwized生成的源程序中找不到这个函数,但是程序是在编译时,由链接器将它链接到程序中。
MFC程序的主要过程
下面的过程函数可以在程序安装文件夹中的wincore.cpp和winfrm.app等文件中寻找。
theApp-> 实例化应用程序对象
CTestApp::CTestApp构造函数-> CWinApp::CWinApp构造函数-> 调用构造函数实例应用程序对象,子类构造函数会调用基类的构造函数
_tWinMain(WinMain函数的宏)-> AfxWinMain函数-> 进入主函数
CTestApp::InitInstance函数-> 初始化应用程序,完成MFC内部管理方面的工作
窗口创建同样遵循设计、注册、创建和显示更新着几个步骤,只是在MFC中,应用程序的窗口设计已经由程序设计好了,它会根据我们在Appwized中的选项而选择已经设计好的哪个窗口。
AfxEndDeferRegisterClass函数-> 注册窗口
CMainFrame::PreCreateWindow函数->
CFrameWnd::PreCreateWindow函数->
AfxDeferRegisterClass(AfxEndDeferRegisterClass函数的宏)->
CFrameWnd::Create函数->
CWnd::CreateEx函数->
CMainFrame::PreCreateWindow函数->
CWnd::CreateEx函数-> 创建窗口
CMainFrame::ShowWindow函数 和 CMainFrame::UpdateWindow函数-> 用于显示和更新窗口
CWinThread::Run函数 和 CWinThread::PumpMessage函数 用于完成消息循环
DefWindowProc函数 默认的窗口过程
Ps:MFC中后缀名为Ex的函数都是扩展函数。MFC程序具有两个窗口(frame框架窗口和view视类窗口),在框架窗口产生之前会调用PreCreateWindow函数。在MFC程序中,窗口的创建是由CreateEx函数实现的,当修改了CreateEx函数的CREATESTRUCT参数时,CreateWindowEx函数会根据参数发生的相应变化来创建窗口。MFC程序对消息的处理实际上是通过消息映射机制来完成的。
简单总结一下MFC程序的运行过程
(1)首先利用全局应用程序对象theApp启动应用程序;
(2)调用全局应用程序对象的构造函数,从而就会调用其基类CWinApp的构造函数,以完成应用程序的一些初始化;
(3)进入WinMain函数;
(4)进入消息循环。
3.窗口类、窗口类对象与窗口的生命周期
如果我们关闭了一个窗口,这个窗口就销毁了,那么该窗口对应的C++窗口类对象销毁了吗?
(1)当一个窗口销毁时,它会调用CWnd::DestroyWindow函数,该函数销毁窗口后,将CWnd::m_hWnd设为NULL;
(2)窗口的生命周期和C++窗口类对象theApp的声明周h期不是一致的。当一个窗口销毁时,与C++窗口类对象没有关系,它们之间的纽带仅仅在于这个C++窗口类内部的成员变 量m_hWnd,该变量保存了与这个C++窗口类对象相关的哪个窗口的句柄。当程序执行到右大括号结束时,窗口对象的生命周期结束。
(3)但是,当C++窗口类对象销毁时,与之相关的窗口也将销毁,因为它们之间的纽带m_hWnd已经断了
参考文献:
http://wenku.baidu.com/link?url=C7-AKI_bgfs3elYH_UWMQIZdOBEutzD5lTQLYLBFch6m8JCit5yOO8bAZ5jsFRHnNDSjGISi517y7CVFlAIxCwNy2TUEpuoaM4ySEA1nN_u
http://blog.163.com/hbu_lijian/blog/static/1261291532010231534248/