1、MFC程序的进入点其实是WinMain,源代码如下:
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }_tWinMain的定义:#define _tWinMain WinMain
2、程序然后,进入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();
//其实pThread和pApp是指向同一个对象,都取出来是因为要分别调用各类中的函数
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication())
goto InitFailure;
/*窗口类只需注册一次,即可供同一程序的后续每一个实例(instance)使用(之所以如此,是因为所有进程同在一个地址空间中),所以我们把RegisterClass这个操作 安排在“只有第一个实例才会进入”的InitApplication函数中。 · 产生窗口,是每一个实例都得进行的操作,所以我们把CreateWindow这个操作安排在“任何实例都会进入”的 InitInstance函数中。*/
// Perform specific initializations
if (!pThread->InitInstance())//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();//在Run中启动线程的消息循环
InitFailure:
#ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE1("Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif
AfxWinTerm();
return nReturnCode;
}
线程对象是在程序进入启动点_tWinMain之前,以全局对象的形式建立的,如下:
CTestApp theApp;
pThread->Run()中Run函数源代码:
int CWinThread::Run() { ASSERT_VALID(this); // for tracking the idle time state BOOL bIdle = TRUE; LONG lIdleCount = 0; // acquire and dispatch messages until a WM_QUIT message is received. for (;;) { // phase1: check to see if we can do idle work while (bIdle && !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) { // call OnIdle while in bIdle state if (!OnIdle(lIdleCount++)) bIdle = FALSE; // assume "no idle" state } // phase2: pump messages while available do { // pump message, but quit on WM_QUIT if (!PumpMessage()) return ExitInstance(); // reset "no idle" state after pumping "normal" message if (IsIdleMessage(&m_msgCur)) { bIdle = TRUE; lIdleCount = 0; } } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); } ASSERT(FALSE); // not reachable }