MFC程序的生存过程

一、MFC的结构

一个标准的MFC程序外貌

 

二、 MFC程序的启动与死亡顺序

那么 ,现在来经历一个MFC程序的完整生命过程

1、创建Application theApp

 

 下图所示,创建一个MFC工程,在MFCApplication1.cpp中有个全局变量CMFCApplication1App theApp;这个全局对象一产生,便执行其构造函数。CWinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。

 2、WinMain登场

用SDK编程序时,程序的入口点是WinMain函数,而在MFC程序里我们并没有看到WinMain函数,哦!~ 原来它是被隐藏在MFC代码里面了。当theApp配置完成后,WinMain登场,慢!细看程序,并没连到WinMain函数的代码啊!这个我也不知道,MFC早已准备好并由链接器直接加到应用程序代码中了,原来它在APPMODUL.CPP里面,好,我们就认为当theApp配置完成后,程序就转到APPMODUL.CPP来了。那执行什么呢?看看下面从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函数的“_t”是为了支持Unicode而准备的一个宏。

 _tWinMain函数返回值是AfxWinMain函数的返回值,AfxWinMain函数定义于WINMAIN.CPP第21行,稍加整理,去芜存菁,就可以看到这个“程序进入点”主要做些什么事:

nt AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
 {
 int nReturnCode = -1;
 CWinApp* pApp = AfxGetApp();

 AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

 pApp->InitApplication();
 pApp->InitInstance()
 nReturnCode = pApp->Run();

 AfxWinTerm();
 return nReturnCode;
 }

AfxGetApp()函数是取得CMyWinApp对象指针,故上面函数第6至8行相当于调用

 CMyWinApp::InitApplication();
 CMyWinApp::InitInstance()
 CMyWinApp::Run();

3、AfxWinInit——AFX内部初始化操作

 AfxWinInit是继CWinApp构造函数之后的第一个操作,主要做的是AFX内部初始化操作,该函数定义于APPINIT.CPP第24行,这里就不掏出来了,你自己搜出来啃吧!

4、执行CWinApp::InitApplication

 AfxWinInit之后的操作是pApp->InitApplication,我们已知道pApp指向CMyWinApp对象,当调用:

 pApp->InitApplication();

 相当于调用:

 CMyWinApp::InitApplication();

 但是你要知道,CMyWinApp继承自CWinApp,而InitApplication又是CWinApp的一个虚拟函数,我们并没有改写它(大部分情况下不需改写它),所以上述操作相当于调用:

 CWinApp::InitApplication();

 此函数定义于APPCORE.CPP第125行,你自己搜出来看吧!我就不搬出来了,里面的操作都是MFC为了内部管理而做的(其实我也看不懂,知道有这回事就好了)。

5、执行CWinApp::InitInstance

 继InitApplication函数之后,AfxWinMain调用pApp->InitInstance。当程序调用:

 pApp->InitInstance();

 相当于调用:

 CMyWinApp::InitInstance();

 但是你要知道,CMyWinApp继承自CWinApp,而InitInstance又是CWinApp的一个虚拟函数。由于我们改写了它,所以上述操作就是调用我们自己(CMyWinApp)的这个InitInstance函数。

6、CFrameWnd::Create产生主窗口(并先注册窗口类)

在已经来到CWinApp::InitInstance了,该函数先new一个CMyFrameWnd对象,从而产生主窗口。在创建CMyFrameWnd对之前,要先执行构造函数CMyFrameWnd::CMyFrameWnd(),该函数用Create函数产生窗口:

 

 CMyFrameWnd::CMyFrameWnd()
 {
     Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL, "MainMenu");
 }

7、窗口显示与更新

 CMyFrameWnd::CMyFrameWnd结束后,窗口已经诞生出来;程序流程又回到CMyWinApp::InitInstance,于是调用ShowWindow函数令窗口显示出来,并调用UpdateWindow函数令程序送出WM_PAINT消息。在SDK程序中,消息是通过窗口函数来处理,而现在窗口函数在哪里、又如何送到窗口函数手中呢?那要从CWinApp::Run说起了。

8、执行CWinApp::Run——程序生命的活水源头

 在执行完CMyWinApp::InitInstance函数后,程序的脚步到了AfxWinMain函数的pApp->Run了,现在我们已知道这将执行CWinApp::Run函数,该函数定义于APPCORE.CPP第391行,下面是程序代码:

int CWinApp::Run()
 {
     if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
     {
         // Not launched /Embedding or /Automation, but has no main window!
         TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.n");
         AfxPostQuitMessage(0);
     }
     return CWinThread::Run();
 }

9、把消息与处理函数连接在一起——Message Map机制

到此,主窗口已经产生,等待的就是各种消息了,然后调用相应的处理函数,然而消息和处理函数怎样连接在一起呢?MFC采用了Message Map机制(消息映射机制),提供给应用程序使用的“很方便的接口”的两组宏,这里就不细讲了。

所以,总的调用结构就是

三、 总结

 

 

参考:

https://blog.csdn.net/csd3176/article/details/100212108

猜你喜欢

转载自blog.csdn.net/sinat_31608641/article/details/107289095