MFC流程

  • 格式:wps
  • 大小:26.00 KB
  • 文档页数:5

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消息用于退出进程,最终结束。)