MFC的流程跟踪
(窗口的设计,注册,创建)
跟踪MFC的程序流程,我们一步一步来,不要怕麻烦!
1 首先是MFC的入口函数:
extern "C"int WINAPI
_tWinMain(HINSTANCEhInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress:4985)
{
// callshared/exported WinMain
returnAfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
2 然后进入AfxWinMain(hInstance, hPrevInstance, lpCmdLine,nCmdShow);
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCEhPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
// pThread,pApp都是指向the App全局对象,不过这两个指针都是the App的父类指针
intnReturnCode = -1;
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
// 这个是完成MFC的初始化
if(!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
gotoInitFailure;
// 应用程序全局初始化,主要是文档相关
if(pApp != NULL && !pApp->InitApplication())
gotoInitFailure;
// 调用子类的Instance函数来实现初始化,这个是重点,窗口的设计
// 注册,创建都在这个函数里面了,中间会调用很多函数
if(!pThread->InitInstance())
{
if(pThread->m_pMainWnd != NULL)
{
TRACE(traceAppMsg,0, "Warning: Destroying non-NULLm_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode =pThread->ExitInstance();
gotoInitFailure;
}
// 消息循环
nReturnCode = pThread->Run();
InitFailure:
#ifdef _DEBUG
// Check formissing 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();
returnnReturnCode;
}
2.1 接下来进入AfxWinInit看看
BOOL AFXAPIAfxWinInit(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_z_ LPTSTR lpCmdLine, _In_ int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
// handlecritical errors and avoid Windows message boxes
SetErrorMode(SetErrorMode(0) |
SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
// setresource handles
AFX_MODULE_STATE* pModuleState =AfxGetModuleState();
pModuleState->m_hCurrentInstanceHandle= hInstance;
pModuleState->m_hCurrentResourceHandle= hInstance;
pModuleState->CreateActivationContext();
// fill inthe initial state for the application
CWinApp* pApp = AfxGetApp();
if(pApp != NULL)
{
//Windows specific initialization (not done if no CWinApp)
pApp->m_hInstance =hInstance;
hPrevInstance; // Obsolete.
pApp->m_lpCmdLine =lpCmdLine;
pApp->m_nCmdShow =nCmdShow;
pApp->SetCurrentHandles();
}
// initializethread specific data (for main thread)
if(!afxContextIsDLL)
AfxInitThread();
returnTRUE;
}
这个函数主要就是完成MFC的初始化,也不需要多解释。其实如果我在控制台程序创建时,勾选了MFC的库,那么在_tmain函数中也会出现这样一个东西,如下:
int _tmain(int argc,TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule =::GetModuleHandle(NULL);
if (hModule != NULL)
{
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(hModule,NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
}
}
else
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: GetModuleHandle 失败\n"));
nRetCode = 1;
}
return nRetCode;
}
2.2 再看看BOOLCWinApp::InitApplication()
BOOLCWinApp::InitApplication()
{
if (CDocManager::pStaticDocManager !=NULL)
{
if (m_pDocManager == NULL)
m_pDocManager =CDocManager::pStaticDocManager;
CDocManager::pStaticDocManager= NULL;
}
if (m_pDocManager != NULL)
m_pDocManager->AddDocTemplate(NULL);
else
CDocManager::bStaticInit =FALSE;
LoadSysPolicies();
return TRUE;
}
这个函数主要就是管理文档的,对目前跟踪流程也没多大用处,先不管它
2.3 接下来再进入我们最关心的函数Instance看看,就是在这个函数中我们进行了窗口的设计,注册,创建,让我们一步一步地揭开它神秘的面纱吧。
BOOL Cmfc4StdApp::InitInstance()
{
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
if(!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
returnFALSE;
}
AfxEnableControlContainer();
EnableTaskbarInteraction(FALSE);
SetRegistryKey(_T(“应用程序向导生成的本地应用程序”));
LoadStdProfileSettings(4); // 加载标准的INI文件
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl),&ttParams);
// 注册应用程序的文档模板,文档模板将用作文档,框架,视口之间的连接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = newCSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(Cmfc4StdDoc),
RUNTIME_CLASS(CMainFrame), // 主SDI框架
RUNTIME_CLASS(Cmfc4StdView));
if(!pDocTemplate)
returnFALSE;
AddDocTemplate(