MFC 學習筆記 2 WinMain函數(shù)的調用過程
MFC是一個類庫, 是別人寫好的一套源碼,實現(xiàn)了對系統(tǒng)API調用的封裝,
與其辛苦學習使用別人設計的類庫,不如好好學習一下其實現(xiàn)原理,
一個EXE窗口程序運行后,由系統(tǒng)載入調用的函數(shù)過程如下:
一、調用VC運行庫文件crtexe.c中的WinMainCRTStartup函數(shù)
大致內容整理如下:
主要的功能是設置命令行參數(shù)和窗口啟動的一些參數(shù)。
void?WinMainCRTStartup(void?)
{
int?argc;???/*?three?standard?arguments?to?main?*/
_TSCHAR?**argv;
_TSCHAR?**envp;
int?mainret;
_TUCHAR?*lpszCommandLine;
STARTUPINFO?StartupInfo;
_startupinfo????startinfo;
__try?{
/*
*?Set?__app_type?properly
*/
?
__set_app_type(_GUI_APP);?
__onexitbegin?=?__onexitend?=?(_PVFV?*)(-1);??
_adjust_fdiv?=?*?_imp___adjust_fdiv;?
_setargv();?
if?(?!__defaultmatherr?)
__setusermatherr(_matherr);
_setdefaultprecision();?
_initterm(?__xi_a,?__xi_z?);?
startinfo.newmode?=?_newmode;
__getmainargs(&argc,?&argv,?&envp,?_dowildcard,?&startinfo);
_initterm(?__xc_a,?__xc_z?);?
lpszCommandLine?=?(unsigned?char?*)_acmdln;
if?(?*lpszCommandLine?==?DQUOTECHAR?)?{
while?(?*++lpszCommandLine?&&?(*lpszCommandLine
????????????????if?(?*lpszCommandLine?==?DQUOTECHAR?)
????????????????????lpszCommandLine++;
}
else?{
while?(*lpszCommandLine?>?SPACECHAR)
lpszCommandLine++;
}
while?(*lpszCommandLine?&&?(*lpszCommandLine?<=?SPACECHAR))?{
lpszCommandLine++;
}
StartupInfo.dwFlags?=?0;
GetStartupInfo(?&StartupInfo?);
mainret?=?WinMain(
GetModuleHandle(NULL),
NULL,
lpszCommandLine,
StartupInfo.dwFlags?&?STARTF_USESHOWWINDOW
??StartupInfo.wShowWindow
:?SW_SHOWDEFAULT
);
__initenv?=?envp;
mainret?=?main(argc,?argv,?envp);
exit(mainret);
}
__except?(?_XcptFilter(GetExceptionCode(),?GetExceptionInformation())?)
{
/*
*?Should?never?reach?here
*/
_exit(?GetExceptionCode()?);
}?/*?end?of?try?-?except?*/
}二、調用WinMain函數(shù)
winmain是一個函數(shù)聲明,每個程序中都要自己實現(xiàn),如果自己沒有實現(xiàn)這個函數(shù),就會使用MFC庫中實現(xiàn),
所以每個Win32程序,必須要有一個winmain函數(shù),因為VC運行庫中的啟動函數(shù)WinMainCRTStartup需要調用這個實現(xiàn)函數(shù)。
如MFC中也有這個函數(shù)聲明
extern?"C"?int?WINAPI
_tWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,
LPTSTR?lpCmdLine,?int?nCmdShow)
{
//?call?shared/exported?WinMain
return?AfxWinMain(hInstance,?hPrevInstance,?lpCmdLine,?nCmdShow);
}三、MFC中的AfxWinMain調用
MFC程序也是先調用WinMain,然后轉到MFC的AfxWinMain函數(shù)。
/////////////////////////////////////////////////////////////////////////////
//?export?WinMain?to?force?linkage?to?this?module
extern?int?AFXAPI?AfxWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,
LPTSTR?lpCmdLine,?int?nCmdShow);
extern?"C"?int?WINAPI
_tWinMain(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,
LPTSTR?lpCmdLine,?int?nCmdShow)
{
//?call?shared/exported?WinMain
return?AfxWinMain(hInstance,?hPrevInstance,?lpCmdLine,?nCmdShow);
}四、AfxWinMain函數(shù)調用CWinApp中的函數(shù)
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)
{
TRACE(traceAppMsg,?0,?"Warning:?Destroying?non-NULL?m_pMainWndn");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode?=?pThread->ExitInstance();
goto?InitFailure;
}
nReturnCode?=?pThread->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;
}
在AfxWinMain函數(shù),扯到好幾個init**初始化函數(shù),其中pThread->InitInstance()函數(shù),就是MFC向導中生成CMyApp::Initstance之類
在這里就可以開始創(chuàng)建窗口,現(xiàn)在可以開始工作了。
BOOL?CTEST1App::InitInstance()
{
CWinApp::InitInstance();?
CTEST1Dlg?dlg;
m_pMainWnd?=?&dlg;
INT_PTR?nResponse?=?dlg.DoModal();
?
return?nResponse;
}
這樣一個MFC程序的來龍去脈,就是這幾個主要的函數(shù)實現(xiàn)的。





