MFC流程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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消息用于退出进程,最终结束。
)。