MFC程序启动过程(VS 2005代码剖析)
2011-01-22 12:32
459 查看
启动前做的事:初始化全局变量。
大概做了以下四件事:
appmodul.cpp 67行 通过调用函数AfxInitialize初始化了MFC的线程局部存储功能和程序全局信息,这些信息最重要的有以下两个:
afxstate.cpp 398行 PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)
afxstate.cpp 117行 THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)
类run time信息初始化
消息映射表生成
全局对象theApp构造
从_tWinMain开始
_tWinMain调用了AfxWinMain函数(以下代码均有删减)
AfxWinMain位于winmain.cpp中,它是程序程序的核心,主要执行了四步:AfxWinInit、InitApplication、InitInstance、Run
先看AfxWinInit函数,它用于初始化框架。
接下来进入InitApplication函数,它完成对整个应用程序的初始化工作。该函数是个虚函数,一般不覆盖它,所以调用的是appcore.cpp中的CWinApp::InitApplication,初始化文档管理器。
InitInstance函数对程序特定的实例进行初始化。它是个虚函数,程序中通过覆盖该函数,可以实现自己的功能。
InitInstance首先创建了一个CMainWindow对象,CMainWindow对象的继承结构如下:
CObject
CCmdTarget
CWnd
CFrameWnd
CMainWindow
对象创建过程如下:
ShowWindow显示窗口
UpdateWindow更新窗口,发送WM_PAINT消息
至此,窗口创建完成。
函数执行流程回到AfxWinMain中,执行Run(),处理消息循环。
启动成功。
大概做了以下四件事:
appmodul.cpp 67行 通过调用函数AfxInitialize初始化了MFC的线程局部存储功能和程序全局信息,这些信息最重要的有以下两个:
afxstate.cpp 398行 PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)
afxstate.cpp 117行 THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)
类run time信息初始化
消息映射表生成
全局对象theApp构造
从_tWinMain开始
_tWinMain调用了AfxWinMain函数(以下代码均有删减)
// appmodul.cpp extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, __in LPTSTR lpCmdLine, int nCmdShow) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }
AfxWinMain位于winmain.cpp中,它是程序程序的核心,主要执行了四步:AfxWinInit、InitApplication、InitInstance、Run
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, __in LPTSTR lpCmdLine, int nCmdShow) { int nReturnCode = -1; CWinThread* pThread = AfxGetThread(); // pThread指向CMyApp CWinApp* pApp = AfxGetApp(); // pApp指向CMyApp // AFX internal initialization AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow); // App global initializations (rare) pApp->InitApplication(); // Perform specific initializations pThread->InitInstance(); nReturnCode = pThread->Run(); return nReturnCode; }
先看AfxWinInit函数,它用于初始化框架。
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance, __in LPTSTR lpCmdLine, int nCmdShow) { // 设置应用程序错误模式,用来指明什么会导致应用程序失败 SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); // 设置应用程序实例句柄和资源句柄 AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); pModuleState->m_hCurrentInstanceHandle = hInstance; pModuleState->m_hCurrentResourceHandle = hInstance; pModuleState->CreateActivationContext(); // fill in the initial state for the application CWinApp* pApp = AfxGetApp(); // Windows specific initialization (not done if no CWinApp) pApp->m_hInstance = hInstance; hPrevInstance; // Obsolete. pApp->m_lpCmdLine = lpCmdLine; pApp->m_nCmdShow = nCmdShow; pApp->SetCurrentHandles(); // 设置应用程序名称、Help和profile文件名 // initialize thread specific data (for main thread) if (!afxContextIsDLL) AfxInitThread(); // 设置消息过滤器hook,消息路由中使用 // Initialize CWnd::m_pfnNotifyWinEvent HMODULE hModule = ::GetModuleHandle(_T("user32.dll")); CWnd::m_pfnNotifyWinEvent = (CWnd::PFNNOTIFYWINEVENT)::GetProcAddress(hModule, "NotifyWinEvent"); return TRUE; }
接下来进入InitApplication函数,它完成对整个应用程序的初始化工作。该函数是个虚函数,一般不覆盖它,所以调用的是appcore.cpp中的CWinApp::InitApplication,初始化文档管理器。
BOOL CWinApp::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; }
InitInstance函数对程序特定的实例进行初始化。它是个虚函数,程序中通过覆盖该函数,可以实现自己的功能。
BOOL CMyApp::InitInstance () { m_pMainWnd = new CMainWindow; // 创建窗口,发送WM_CREATE消息 m_pMainWnd->ShowWindow (m_nCmdShow); // 显示窗口 m_pMainWnd->UpdateWindow (); // 更新窗口,发送WM_PAINT消息 return TRUE; }
InitInstance首先创建了一个CMainWindow对象,CMainWindow对象的继承结构如下:
CObject
CCmdTarget
CWnd
CFrameWnd
CMainWindow
对象创建过程如下:
CMainWindow::CMainWindow () { Create (NULL, _T ("The Hello Application")); } BOOL CFrameWnd::Create(LPCTSTR lpszClassName, // 窗口类名 LPCTSTR lpszWindowName, // 窗口名 DWORD dwStyle, // 窗口风格 const RECT& rect, // 初始位置 CWnd* pParentWnd, // 父窗口句柄 LPCTSTR lpszMenuName, // 菜单资源名称 DWORD dwExStyle, // 扩展风格 CCreateContext* pContext) // 上下文,用在文档/视图结构程序中初始化外框窗口 { HMENU hMenu = NULL; if (lpszMenuName != NULL) { // load in a menu that will get destroyed when window gets destroyed HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, ATL_RT_MENU); hMenu = ::LoadMenu(hInst, lpszMenuName); } m_strTitle = lpszWindowName; // save title for later CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext); return TRUE; } BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam) { // allow modification of several common create parameters CREATESTRUCT cs; cs.dwExStyle = dwExStyle; cs.lpszClass = lpszClassName; cs.lpszName = lpszWindowName; cs.style = dwStyle; cs.x = x; cs.y = y; cs.cx = nWidth; cs.cy = nHeight; cs.hwndParent = hWndParent; cs.hMenu = nIDorHMenu; cs.hInstance = AfxGetInstanceHandle(); cs.lpCreateParams = lpParam; // 虚函数,可以覆盖从而实现自己的窗口类。该函数中检查 // lpszClassName是否为NULL,如果为NULL,则注册默认窗口类 PreCreateWindow(cs); AfxHookWindowCreate(this); HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); AfxUnhookWindowCreate(); return TRUE; } // 通过覆盖这个函数,可以创建自己的窗口类,也可以修改CREATESTRUCT内容 // ,从而指定特定的窗口样式。 BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) { if (cs.lpszClass == NULL) { // 注册默认窗口类,MFC有默认的几种窗口类ID,可通过AfxDeferRegisterClass宏注册 AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG); cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background } if (cs.style & FWS_ADDTOTITLE) cs.style |= FWS_PREFIXTITLE; cs.dwExStyle |= WS_EX_CLIENTEDGE; return TRUE; }
ShowWindow显示窗口
UpdateWindow更新窗口,发送WM_PAINT消息
至此,窗口创建完成。
函数执行流程回到AfxWinMain中,执行Run(),处理消息循环。
启动成功。
相关文章推荐
- 深入剖析 MFC程序的启动过程
- vc2005编译过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的彻底解决
- MFC程序执行过程深入剖析
- MFC程序启动过程
- arm:启动代码判断是从nand启动还是从norflash启动,拷贝程序到内存的过程
- vs 2005调试程序是出现无法在web服务器上启动调试,调试失败的解决方法。
- 解决VS调试过程中无法启动程序或找不到元素
- 关于在android程序执行过程中使用Intent启动另一个活动后,同个方法未执行的代码是否会继续执行。
- IDE-----VS2005运行过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的解决
- ++编译过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的彻底解决
- MFC程序执行过程剖析
- 【转】C++编译过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的彻底解决
- MFC程序的启动过程与相关函数执行顺序
- VS下EXE可执行文件启动代码剖析(4)_cinit 函数
- VS2013 中MFC程序编译过程出现 RC2108错误
- MFC程序的启动过程与相关函数的执行顺序
- vs 2005存储过程分页主要代码
- VS 2013 中MFC程序编译过程出现 RC2108错误
- MFC程序的启动过程与相关函数执行顺序
- MFC窗口程序启动运行机制剖析