使用MFC编程的程序员刚开始都会提出这样一个问题:我的程序是从哪儿开始执行的?回答是: 从WinMain()开始执行的。提出这样的问题是由于在他们所编写的MFC应用中看不到WinMain()函数。这个函数是隐藏在MFC框架中,MFC 的设计者将它作得很通用(这主要得益于Window的消息驱动的编程机制,使得作一个通用的WinMain()很容易),因此在一般情况下,无需更改 WinMain()的代码,MFC的设计者也不提倡程序员修改WinMain()的代码。在MFC中,实际实现WinMain()的代码是 AfxWinMain()函数(根据其前缀Afx就知道这是一个全局的MFC函数)。
一个Win32应用程序(或进程)是由一个或多 个并发的线程组成的,其中第一个启动的线程称为主线程,在Window下,一般将线程分成两大类,界面线程和工作线程,工作线程就是一般的线程,它没有窗 口,没有消息队列等,界面线程拥有一个或多个窗口,拥有一个消息队列和其他专属于界面线程的元素。在讨论AfxWinMain()之前,首先要简略提一下 MFC中的两个重要的类,CWinThread和CWinApp,CWinThread是用来封装界面线程的类,CWinApp是从CWinThread 派生而来的。在CWinThread中,有两个很重要的虚拟函数InitInstance()和ExitInistance(),MFC的程序员应该对这 两个函数应该很熟悉。在CWinApp中,增加了另外一个虚拟函数InitApplication(),讨论AfxWinMain()的主要目的是看这些 函数是如何被调用的。
AfxWinMain()的代码如下:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
int nReturnCode = -1;
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
// Perform specific initializations
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;
}
nReturnCode = pThread->Run();
InitFailure:
AfxWinTerm();
return nReturnCode;
}
在上面的代码中,AfxGetThread()返回的是当前界面线程对象的指针,AfxGetApp()返回的是应用程序对象的指针,如果该应用程序 (或进程)只有一个界面线程在运行,那么这两者返回的都是一个全局的应用程序对象指针,这个全局的应用程序对象就是MFC应用框架所默认的theApp对 象(每次使用AppWizard生成一个SDI或MDI应用程序时,AppWizard都会添加CYourApp theApp这条语句,AfxGetApp()返回的就是这个theApp的地址)。
CWinApp::InitApplication(), CWinThread::InitInstance(), CWinThread::ExitInstance()的调用情况。
CWinThread::PumpMessage() line 848 + 30 bytes
CWnd::RunModalLoop(unsigned long 4) line 3489 + 19 bytes
CDialog::DoModal() line 539 + 12 bytes
CIntelligentFtpApp::InitInstance() line 65 + 11 bytes
AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00151f26, int 1) line 39 + 11 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00151f26, int 1) line 30
WinMainCRTStartup() line 198 + 54 bytes
KERNEL32! 7c816fd7()
本文深入探讨了MFC编程中程序的入口WinMain()函数的实际实现——AfxWinMain(),并分析了MFC框架如何通过主线程和应用程序对象初始化整个应用流程。
1213

被折叠的 条评论
为什么被折叠?



