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)的。