MFC创建流程详解

(0)MFC学习: 
1.CObject类为MFC总类,该类下面有一个重要的类CCmdTarget。而CCmdTarget类下面又有四个重要的继承类,分别为:CWinThreadCDocumentCDocTemplate 
       CWnd类。所以,可以得出一个大概继承图,如图所示: 
                     CObject--->CCmdTarget ---->CWinThread ---->CWinApp 
                                                          ----->CDocTemplate 
                                                          ----->CDocument 
                                                          ----->CWnd 
       
其中CWnd类下属又有几个重要的继承类,分别为CFrameWndCDialogCViewControls 
                     CWnd---->CFrameWnd 
                             ---->CDialog 
                             ---->CView 
                             ---->Controls 
    
归纳一下,CCmdTarget类为MFC主要类的总钢。应用程序(CWinApp)间接继承于它,文档模板(CDocTemplate)继承于它,文档类(CDocument)继承于它,还有一个非常重要的类窗口类(CWnd)继承于它。 
       窗口类是一切Windows可见窗口,(包括主窗口,子框窗口,对话框,控件,View窗口)的父类。凡是能可见的,基本上是继承于CWnd,而抽象于其中的(即不可见的)则不继承于它。

小结:只要在新创建的MFC项目中,找到全局theApp对象,框架类构造函数,doc类构造函数,view类构造函数,CWinApp派生类的InitInstance()这几处打断点,就可以跟踪MFC窗口的整个创建流程。

(1)当我们使用vs2005创建MFC工程的时候,默认已经产生了整个MFC框架源文件。如下:


(2)打开MyWinApp,找到如下两个位置,打断点,并跟踪函数的调用堆栈,可以发现全局对象theApp首先被构造,也即通过程序启动函数__tmainCRTStartup构造:



(3)接下来继续执行到InitInstance,可以发现调用了windows程序中最典型的入口函数,这里是AfxWinMain(带有Afx是全局函数),进入AfxWinMain函数,可以看到:



由此可以大致看到MFC程序的启动流程:

第一、它会获得Application Object的指针(亦CWinApp派生对象的指针),在此是获得MyWinApp的指针,以备后用。它是通过下面这句来实现的: 
            CWinApp* pApp = AfxGetApp();  //AfxGetApp为全局函数,不属于任何类,注:凡是函数前有Afx字样的都是全局函数。

第二、调用AfxWinInit(...)函数,用作MFC GUI程序初始化的一部分

第三、用上面获得的pApp调用InitApplication()函数,如下:pApp->InitApplication(); 

第四、用pApp调用InitInstance()函数,如下:pApp->InitInstance(); 

第五、用pApp调用Run()函数,如下: nReturnCode = pApp->Run();  

第六、最后调有AfxWinTerm函数,结束该应用程序。 

(4)AfxWinInit和InitApplication做了窗口必要的一些初始化操作,派生类一般不需要改写它们。我们重点看看InitInstance函数。


可以看到,InitInstance中创建了文档模板,在最后通过调用m_pMainWnd->ShowWindow(SW_SHOW);显示窗口。我们知道windows创建窗口的流程需要先注册窗口类,在创建窗口,这里我们没有发现这些功能的操作。

(5)在(1)步中,我们的MFC文件框架可以看到一个框架类文件MainFrm.cpp,很明显这个就是我们的主框架窗口,打开文件,并在CMainFrame构造函数打断点分析,如下:


(6)在上面的截图中我们可以很清楚的看到函数调用堆栈,最终我们定位到CreateNewFrame函数中,这个函数里面就调用创建窗口函数,我们进去看看:


m_pFrameClass->CreateObject()创建函数的导入涉及到MFC内部定义的IMPLEMENT_DYNCREATE宏及其相关的其他宏定义,具体可以参见深入浅出MFC——Win32程序基本概念(一)系列文章。这里我们不作深入讨论。我们重点看看pFrame->LoadFrame函数,这个就是对我们创建的空的主框架对象的操作,包括注册窗口类,参见窗口。

(7)依然在打断点进入LoadFrame函数,如下:


这里我们终于看到了和窗口类注册,创建窗口相关的操作了。AfxDeferRegisterClass函数和Create函数就是执行这两个操作的。老办法,打断点进入函数查看:


可以看到,函数内部根据不同的注册类型分别创建不同的窗口类,这里我们调用了_AfxRegisterWithIcon函数,进入到此函数,我们将会看到其调用了AfxRegisterClass,执行真正的窗口类注册。再次进入AfxRegisterClass看看:


至此,窗口类的注册结束。

(9)接着,我们进入Create看看MFC如何创建窗口:


我们再进入CreateEx看看:


可以看到,最终调用了AfxCtxCreateWindowEx完成窗口创建。

==========================================================================================

至此,MFC窗口类注册,窗口创建流程完结。

==========================================================================================

应用程序对象、文档模板对象、文档对象、视图对象和框架窗口对象之间的关系

(转自:http://www.jizhuomi.com/software/223.html)

文档、视图、框架结构中涉及到的对象主要有:应用程序对象、文档模板对象、文档对象、视图对象和框架窗口对象等。根据上一节的概述,大家对它们的概念已经有所了解了,下面就对它们之间的关系进行总结和概括,并对各个关系中用到的类的成员函数进行介绍。

       1. 应用程序对象保存了一个文档模板的列表。在任何对象中调用全局函数AfxGetApp都可以获得应用程序对象的指针。通过调用CWinAppEx::GetFirstDocTemplatePosition、CWinAppEx::GetNextDocTemplate函数可以遍历所有的文档模板。

       2. 文档模板对象用于维护文档、视图和框架窗口的映射关系,它包含有一个已打开文档的列表。我们可以通过调用CDocTemplate::GetFirstDocPosition、CDocTemplate::GetNextDoc来遍历该文档模板对应的所有文档。

       3. 框架窗口对象中包含有指向当前活动视图对象的指针。AfxGetApp()->m_pMainWnd即为主框架窗口对象的指针。我们可以通过调用CFrameWndEx::GetActiveView来获取当前活动视图对象的指针,并且使用CFrameWndEx::GetActiveDocument函数可以获得当前活动视图对应的文档。

       4. 文档对象中维护着该文档的视图列表,以及创建该文档的文档模板对象的指针。我们可以通过调用CDocument::GetFirstViewPosition,CDocument::GetNextView来遍历该文档关联的所有视图,调用CDocument::GetDocTemplate获取创建该文档的文档模板对象的指针。

       5. 视图是框架窗口的子窗口,它保存有指向对应的文档对象的指针。我们可以通过调用CView::GetParentFrame获取其所属的框架窗口对象的指针,调用CView::GetDocument获取该视图对应的文档对象的指针。

       另外,在MDI多文档程序中,调用CMDIFrameWnd::MDIGetActive可以获取当前活动的MDI子窗口。

       文档和视图的关系

       应用程序可以是单文档程序也可以是多文档程序。单文档程序中主框架窗口和文档框架窗口重合,而多文档程序的主框架窗口中有客户窗口,客户窗口中又包含了多个文档框架窗口。

       文档和视图是一对多的关系。一个文档可以对应多个视图,例如在Word中一个文档有普通视图、大纲视图、Web版式视图、阅读版式视图等多种视图。而一个视图只能属于一个文档。最简单的应用程序是单文档单视图程序,除此之外还有单文档多视图程序、多文档程序等。

       每个文档对象都保存着一个视图列表,可以通过CDocument::AddView函数添加视图,通过CDocument::RemoveView函数删除视图,在数据发生变化时调用CDocument::UpdateAllViews函数更新所有视图。

       在MFC中文档可以有三种视图模式:

       1. 文档有多个视图对象,它们是同一个视图类的对象,每个视图对象位于一个独立的文档框架窗口中。

       2. 文档的基于同一个视图类的多个视图对象,位于同一个文档框架窗口中。Word的子窗口就是这种视图模式。

    3.文档的视图对象属于不同的视图类,但所有的视图对象位于同一文档框架窗口中。 

       鸡啄米在网上找到了一张分别对应三种视图模式的图如下: 

VS2010/MFC编程入门之四十(文档、视图和框架:各对象之间的关系)



==========================================================================================

参阅:

http://www.jizhuomi.com/software/223.html

http://www.cnblogs.com/shipfi/archive/2005/10/13/121629.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值