MFC执行过程详解

摘要:
■ AFXCMN。H: 使用Windows9x添加的常规控件的MFC程序需要加载此文件。■ AFXCOLL。H: 所有使用CollectionClass的程序都需要加载此文件。■ AFXRES。H: MFC程序的RC文件必须加载到此文件中。MFC具有标准Windows资源ID的默认定义,该定义位于头文件中。配置完成后,TWinMain登场。注意,我们没有编写WinMain代码。WinMain已经由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,而抽象于其中的(即不可见的)则不继承于它。

 

2.MFC头文件:
      
STDAFX.H:该文件用来作为Precompiled header file,其内只是载入其它的MFC头文件。

AFXWIN.H:每个MFC程序都必须载入它,因为它以及它所载入的文件声明了所有的MFC类。此文件内包含AFX.H,后者又包含AFXVER_.H,后者又包含AFXV_W32.H,后者又包含WINDOWS.H

AFXEXT.H:凡使用工具栏、状态栏的程序必须载入此文件。

AFXDLGS.H:凡使用通用型对话框(Common Dialog)的MFC程序要载入此文件。

AFXCMN.H:凡使用Windows9x新增的通用型控件(Common Control)之MFC程序需载入此文件。

AFXCOLL.H:凡使用Collections Class(处理数据结构如数据,链表类等)之程序需载入此文件。

AFXDLLX.H:凡MFC extension DLLs需载入此文件。

AFXRES.H:MFC程序的RC文件必须载入此文件。MFC对于标准Windows资源(如File,Edit等)的ID均有默认定义,这此定义在该头文件内。

 

 

3.什么是Precompiled Header
      
一个应用程序在发展过程中需不断的编译,而Windows程序载入的.H头文件非常巨大且内容不变,编译器如果不Precompiled的话,每次需要编译的时间非常多,所以Precompiled Header就是将.H文件一次编译后的结果存储起来,第二次编译时就可以直接从磁盘中读取。


 

4.关于应用程序的进入点WinMain和窗口过程WndProc
       MFC
代码由于类封装了API,所以,根本就看不到程序的进入WinMain和窗口处理函数WndProc,但是,由于这两个函数有相当程序的不变性,所以,MFC就把有着相当固定行为的WinMain内部操作封装在WinApp中,把有着相当固定行为的WndProc内部操作封装在CFrameWnd中。也就是说:
      
CWinApp代表程序本体         ■CFrameWnd代表一个主框窗口(Frame Window)

 

 

5.CWinApp类取代了SDK中的WinMain地位:
    CWinApp本身就代表一个程序本体,程序本体是指与程序本身有关而不与窗口有关的数据或动作。比如,WinMain传递的四个参数,注册窗口类,分派消息等。比如,CWinApp类中就定义了WinMain函数的四个参数(m_hInstance,m_hPrevInstance,m_lpCmdLine,m_nCmdShow)。还定义了一些重要的如InitApplication(),InitInstance(),Run()等函数。传统的WinMain函数就是由此三个函数完成。
    另外,CWinApp中还应该有个主窗口的handle,是的,但它不在CWinApp类中,而是在CWinThread类中实现,在CWinThread类中,有一个指向窗口类的指针的成员变量。如下所示 CWnd* m_pMainWnd

 

6.CFrameWnd类取代了SDK中的WndProc地位
    众所周知,WndProc是用来处理窗口(包括初始化,处理消息,显示等)的函数,那么CFrameWnd也是,首先在头文件中,我们要继承一个CFrameWnd的类,并在此定义要处理的消息(DECLARE_MESSAGE_MAP),然后,在源文件中,定义该类的消息实现(BEGIN_MESSAGE_MAP,END_MESSAGE_MAP)

 

7.MFC中阴晦的WinMain:
    首先,我们必须在源文件中定义了一个CMyWinApp的实体它是第一步操作。(如: CMyWinApp MyWinApp;注:代码详见:G:\Program\MyMFC\Hello\Hello.dsw),CMyWinApp继承自CWinApp,CMyWinApp无构造函数,但需调用CWinApp构造函数。配置好MyWinApp实体的一些信息,包括获得该线程的句柄,线程的ID,该实体的句柄等。配置完后,_tWinMain登场,注意,我们没有撰写WinMain的代码,WinMain是MFC早已准备好并由链接器直接加到应用程序代码中的。_tWinMain是为了支持Unicode而准备的一个宏,实质还是WinMain。好,_tWinMain函数做了什么工作呢?它只是在里面调用AfxWinMain函数。如下:returnAfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); AfxWinMain是一个全局的函数,并不属于任一个类。
    下面让我们来看一看AfxWinMain函数做了些什么工作?

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

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

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

第四、用pApp调用InitInstance()函数,如下:pApp->InitInstance(); InitInstance函数详见后解...

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

第六、最后调有AfxWinTerm函数,结束该应用程序。
    所以,主要的AfxWinMain做的工作就应该如下代码所示:
   
int AFXAPIAfxWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

{

int nReturnCode = -1;

CWinApp* pApp = AfxGetApp();   //详见第8

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow); //详见第9

pApp->InitApplication();     //详见第10

pApp->InitInstance();        //详见第11

nReturnCode = pApp->Run();   //详见第12

AfxWinTerm();

return nReturnCode;

}  

 

 

8.AfxGetApp是如何获得CWinApp继承类(在此即CMyWinApp)的实体的指针的?
       AfxGetApp
是一个全局函数,定义于AFXWIN1.INL中,如下:
      
_AFXWIN_INLINE CWinApp* AFXAPIAfxGetApp() { returnafxCurrentWinApp; }
   
afxCurrentWinApp则又是一个宏,定于AFXWIN.H中:

    #define afxCurrentWinAppAfxGetModuleState()->m_pCurrentWinApp
   而在CWinApp类的构造函数中,有一段代码是这样定义的:
   
AFX_MODULE_STATE* pModuleState =AfxGetModuleState();

      pModuleState->m_pCurrentWinApp = this;

      这样,应该看清楚他是如何获得CWinApp继承类(在此是指CMyWinApp类)的实体的指针了吧?
      
那么,pApp->InitApplication() / pApp->InitInstance() / pApp->Run()就可以理解成这样:
       CMyWinApp::InitApplication(); / CMyWinApp::InitInstance(); / CMyWinApp::Run()
因为CMyWinApp只继承了InitInstance的实现,所以,就导致调用:
       CMyApp::InitApplication(); / CMyWinApp::InitInstance(); / CWinApp::Run()

9.AfxWinInit ----AFX内部的初始化操作:
       AfxWinInit
CWinApp构造函数后的第一个操作,也就是第二步操作,以下是它的操作摘要:
      
BOOL AFXAPIAfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)

    {

ASSERT(hPrevInstance == NULL);

AFX_MODULE_STATE* pState = AfxGetModuleState();

pState->m_hCurrentInstanceHandle = hInstance;

pState->m_hCurrentResourceHandle = hInstance;

// fill in the initial state for the application

CWinApp* pApp = AfxGetApp();//还是获得CMyWinApp实体的指针。

if (pApp != NULL)

{

// Windows specific initialization (not done if no CWinApp)

pApp->m_hInstance = hInstance;  //设定WinMain四个参数的初始值。

pApp->m_hPrevInstance = hPrevInstance;

pApp->m_lpCmdLine = lpCmdLine;

pApp->m_nCmdShow = nCmdShow;

pApp->SetCurrentHandles();

}

if (!afxContextIsDLL)

AfxInitThread();

return TRUE;

}


10.CWinApp::InitApplication
()函数:
       AfxWinInit
函数对内部初始化之后,进入第三步操作:InitApplication,由于CMyWinApp继承自CWinApp,InitApplication又是CWinApp的一个虚拟函数,我们在CMyWinApp中没有改写它(大部分情况下也不需要改写它),所以我们调用的是CWinApp::InitApplication(),下面我们来看看InitApplicationMFC中做了什么动作?
      
BOOL CWinApp::InitApplication()

{

if (CDocManager::pStaticDocManager != NULL)

{

if (m_pDocManager == NULL)

CDocManager::pStaticDocManager = NULL;

}

if (m_pDocManager != NULL)

m_pDocManager->AddDocTemplate(NULL);

else

CDocManager::bStaticInit = FALSE;

return TRUE;

}

      这些操作都是MFC为内部管理而做的。只要记住一点,我们的派生类无需改写它,它是关于CDocManager的类,关于该类详见后解...

免责声明:文章转载自《MFC执行过程详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python之socket_tcpVS2017 WinFrom打包设置与教程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Visual C++ MFC/ATL开发-提高篇

MFC简单打印方法通过MFC来完成打印作业有很多的方法,应用场合也有所不同。我们通常是利用视图框架在MFC基础之上按照OnPreparePrinting() à OnBeginPrinting() ? à OnPreprareDC() à OnPrinting () à OnEndPrinting()的顺序来编程的。对于我们使用单文档或者多文档的视图框架...

MFC【exe】工程中的文件大致信息(翻译的)

在工程文件夹中有个readme文件,下面是翻译过来的。 ======================================================================== MICROSOFT FOUNDATION CLASS LIBRARY : Down1====================================...

MFC常用操作总结

// 获取文件基本属性 #if 0 CFile成员: BOOL GetStatus(CFileStatus& rStatus) const; static BOOL PASCAL GetStatus(LPCTSTR lpszFileName,CFileStatus& rStatus,CAtlTransactionMa...

MFC的简单加法器(二)

   创建对话框主要分两大步,第一,创建对话框资源,主要包括创建新的对话框模板、设置对话框属性和为对话框添加各种控件;第二,生成对话框类,主要包括新建对话框类、添加控件变量和控件的消息处理函数等。鸡啄米在本节中先讲讲怎样创建对话框模板和设置对话框属性。        创建基于对话框的应用程序框架        之前鸡啄米创建的HelloWorld程序是单文...

MFC中使用Tab Control从CTabCtrl控件类继承自己的类(CTabSheet)来处理。

使用Tab Control,并且从CTabCtrl控件类继承自己的类(CTabSheet)来处理。首先我先介绍一下如何使用CTabSheet。先要制作子对话框类,这次的子对话框类不要从CPropertyPage继承,而是直接从CDialog继承。并且各个子对话框资源的属性应设置为:Style为Child, Border为None。在主对话框资源中,加入一个...

MFC逆向-消息响应函数的定位

MFC  ==   Microsoft Foundation Class,微软基础类库,他封装了Windows API以便用户更快速的开发界面功能程序然而该库及其庞大而复杂,需要有C++的功底否则很难解决bug,逆向起来也是需要一定技巧。本人曾总结过Windows消息大全,他截取自winuser.h  commctrl.h,如果将这些消息以及通知码(LV...