4.探索AfxWinMain
在WinMain函数的定义中可以发现仅有一行:
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
所以WinMain的具体实现是交给AfxWinMain完成的。
打开WinMain.cpp查看定义:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
int nReturnCode = -1;
CWinThread* pThread = AfxGetThread(); //CWinApp派生于CWinThread
CWinApp* pApp = AfxGetApp(); //CTestApp派生于CWinApp
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance,lpCmdLine, nCmdShow))
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL &&!pApp->InitApplication()) //初始化应用程序,完成MFC内部初始化管理方面的工作
goto InitFailure;
// Perform specific initializations
if (!pThread->InitInstance()) //初始化实例,完成注册窗口类、创建窗口、显示窗口、更新窗口等工作
{
if (pThread->m_pMainWnd != NULL)
{
TRACE(traceAppMsg, 0,"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)
{
TRACE(traceAppMsg, 0,"Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif
AfxWinTerm();
return nReturnCode;
}
关键行1:CWinThread* pThread =AfxGetThread();
我们转到AfxGetThread函数的定义,位于THREDCORE.CPP文件中。
CWinThread* AFXAPI AfxGetThread()
{
// check for current thread in modulethread state
AFX_MODULE_THREAD_STATE* pState =AfxGetModuleThreadState();
CWinThread* pThread =pState->m_pCurrentWinThread;
return pThread;
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------
发现与书中相比少了如下几行:
//if no CWinThreadfor the module, then use the global app.
if(pThread == NULL)
pThread = AfxGetApp();
根据MSDN2013对于AfxGetThread的批注:
If you are porting an MFC project calling AfxGetThread fromVisual C++ versions 4.2, 5.0, or 6.0,AfxGetThread calls AfxGetApp if no thread is found. In VisualC+ .NET and later,AfxGetThread returnsNULL if nothread was found. If you want the application thread, you must call AfxGetApp.
翻译:
如果你正在移植一个MFC项目,并且是从旧版本的VC++(如VC++6.0)调用AfxGetThread函数,那么AfxGetThread调用AfxGetApp如果没有找到线程。(如上面的代码:pThread=AfxGetApp(); )在之后的VC版本中,如果没有找到线程,那么这个函数返回值是NULL。如果你想要获得应用程序线程,必须调用AfxGetApp。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
关键行2:CWinAPP* pApp =AfxGetApp ();
查看AfxGetApp定义:位于AFXWIN1.INL
_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
{ return afxCurrentWinApp; }
查看afxCurrentWinApp的定义:位于AFXWIN.H
#define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp
根据前面CWinApp构造函数的定义,m_pCurrentWinApp存放的就是theApp对象。
也就是说,对于Test程序,pApp指向的是theApp这个全局对象。
但是调用了AfxGetApp函数也没有明白pThread指针指向哪里,书中是在pThread为NULL时让pThread = AfxGetApp();,而现在没有这行赋值语句?
这里我的猜想是pThread会在调用其他函数的时候来得到应用程序线程(Test应用程序只有一个线程,多线程的问题以后再研究),因为pThread->InitInstance(),pThread->ExitIn