您的位置:首页 > 编程语言

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函数(以下代码均有删减)

// 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(),处理消息循环。

启动成功。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐