MFC执行流程

来源:互联网 发布:软件开发费用包括 编辑:程序博客网 时间:2024/04/30 08:25

MFC流程  


|字号 订阅

MFC程序文件名为Test.
所以产生的5个类分别为
1、CAboutDlg继承于CDialog
2、CMainFrame继承于CFrameWnd
1、CTestApp继承于CWinApp
1、CTestDoc继承于CDocument
1、CTestView继承于CView
一、窗口产生流程
1、设计窗口类 2、注册窗口类 3、产生窗口 4、显示窗口 5、更新窗口

二、MFC中的细节
1、WinMain函数的地址
在C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\APPMODUL.CPP文件中

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 LPTSTR lpCmdLine, int nCmdShow)
{
 // call shared/exported WinMain
 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

其中_tWinMain是WinMain的宏
定义如下: (此定义在文件C:\Program Files\Microsoft Visual Studio\VC98\Include\TCHAR.H中)
#define _tWinMain   WinMain
而_tWinMain调用的是AfxWinMain.

2、theApp全局对象
先于WinMain运行产生全局对象,在程序入口函数WinMain加载时,系统就已经为全局变量或全局对象分配了存储空间,并为它们赋了初始值。存放在静态数据区。
每一个MFC程序有且仅有一个从应用程序类(CWinApp)派生的类。每一个MFC程序实例有且仅有一个该派生类的实例化对象,也就是theApp全局对象。该对象表示应用程序本身。由于在子类的构造之前会先调用其父类的构造函数。从而就把我们程序自己创建的类与Microsoft提供的基类关联起来了。

3、CWinApp类的定义
CWinApp类的定义在C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\appcore.cpp中
其构造函数的代码中有一条这样的语句
pModuleState->m_pCurrentWinApp = this;
根据C++继承性原理,这个this对象代表的是子类CTestApp的对象,即theApp.

4、AfxWinMain函数
!(Afx前缀的函数代表应用程序框架(Application Framework)函数。应用程序框架实际上是一套辅助我们生成应用程序的框架模型。该模型把多个类进行了一个有机的集成,可以根据该模型提供的方案设计我们自己的应用程序。在MFC中,以Afx为前缀的函数都是全局函数,可以在程序的任何地主调用它们。)

Afx函数在文件C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\WINMAIN.CPP中定义

(1)其中有2行代码
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp()
获得一个CWinThread类型的指针.CWinApp派生于CWinThread类
AfxGetThread函数定义在文件C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\THRDCORE.CPP
AfxGetThread最终调用的是函数AfxGetApp(),所以这两个指针是一致的。
(AfxGetApp()最终返回的是afxCurrentWinApp,它是要生成全局对象theApp的this指针)

AfxGetApp()定义在C:\Program Files\Microsoft Visual Studio\VC98\MFC\Include\AFXWIN1.INL
AfxCurrentWinApp定义在C:\Program Files\Microsoft Visual Studio\VC98\MFC\Include\AFXWIN.H

(2)其中3段代码完成WIN32程序所需要的几个步骤:
设计窗口类、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环、窗口过程函数。
1、 if (pApp != NULL && !pApp->InitApplication())
  goto InitFailure;

 // Perform specific initializations
2、 if (!pThread->InitInstance())
 {
  if (pThread->m_pMainWnd != NULL)
  {
   TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
   pThread->m_pMainWnd->DestroyWindow();
  }
  nReturnCode = pThread->ExitInstance();
  goto InitFailure;
 }
3、 nReturnCode = pThread->Run();

(2).1:
pApp首先调用InitApplication函数,该函数完成MFC内部管理方面的工作。
(2).2
接着,调用pThread的InitInstance函数,这是个虚函数。实际上调用的是子类WTestApp的InitInstance函数。

三、MFC框架窗口
1、设计和注册窗口
MFC已经为我们预定义了一些默认的标准窗口类,只需要选择所需的窗口类,然后注册就可以了。
窗口类的注册是由AfxEndDeferRegisterClass函数完成的,该函数的定义位于WINCORE.CPP中。AfxEndDeferRegisterClass函数首先判断窗口类的类型,然后赋予其相应的类名(wndcls.lpszClassName变量),这些类名都是MFC预定义的,之后就调用AfxRegisterClass函数注册窗口类,后者的定义位于WINCORE.CPP中。

我们创建的这个MFC应用程序Test,实际上有两个窗口。其中一个是CMainFrame类的对象所代表的应用程序框架窗口。该类有一个PreCreateWindow函数,这是在窗口产生这前被调用的。该函数首先调用CFrameWnd的PreCreateWindow函数。后者位于源文件WINFRM.CPP中。在CFrameWnd的PreCreateWindow函数中调用了AfxDeferRegisterClass函数,该函数是一个宏.有如下定义:
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
所以调用的是AfxEndDeferRegisterClass()函数用于注册窗口类。

2、创建窗口
按照WIN32程序编写步骤,设计窗口类并注册窗口类之后,应该是创建窗口了。在MFC程序中,窗口的创建功能是由CWnd类的CreateEx函数实现的,该函数的声明位于AFXWin.h文件中,定义位于WINCORE.CPP中。
先是由CFrameWnd类调用LoadFrame函数,在这个函数中调用Create函数(其声明也位于AFXWin.h中,其定义位于WINFRM.CPP文件中),在create函数中调用CWnd类的CreateEx函数。

在CWnd类的CreateEx函数实现代码中,可以发现该函数中又调用了PreCreateWindow函数,后者是一个虚函数。因此,这里实际上调用的是子类,即CMainFrame类的PreCreateWindow函数。之所以在这里再次调用这个函数,主要是为了在产生窗口之前让程序员有机会修改窗口外观,例如,去掉窗口的最大化按钮等,PreCreateWindow函数的参数就是为了实现这个功能而提供的。该参数的类型是CREATETRUCT结构。如果在子类的PreCreateWindow函数中修改了CREATETRUCT结构体的值,那么,接下来调用CreateWindowEx函数时,其参数发生相应的改变,从而就会创建一个符合我们要求的窗口。

3、显示窗口和更新窗口
在Test程序的应用程序类CTestApp中有一个名为m_pMainWnd的成员变量。该变量是一个CWnd类型的指针,它保存了应用程序框架窗口对象的指针。也就是说,是指向CMainFrame对象的指针。在CTestApp类的InitInstance函数实现内部有如下两句代码 。
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
这两行代码的功能是显示应用程序框架窗口的更新这个窗口。

4、消息循环
CWinThread类的Run函数就是完成消息循环这一任务的,该函数是在AfxWinMain函数中调用的。
pThread->Run();
CWinThread类的Run函数的定义位于THRDCORE.CPP文件中。该函数的主要结构是一个for循环,该循环在接收到一个WM_OUIT消息时退出。
(按右上角的叉,对应的是发送一个WM_CLOSE消息,WM_CLOSE消息发送一个WM_DESTROY消息,用于消除窗口,WM_DESTROY消息最后发送一个WM_QUIT消息用于退出进程,最终结束。)

原创粉丝点击