友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第69部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
#0039 InitFailure:
#0040
#0041 AfxWinTerm();
#0042 return nReturnCode;
#0043 }
图6…4 Windows 程序进入点。源代码可从MFC 的WINMAIN。CPP 中获得。
367
…………………………………………………………Page 430……………………………………………………………
第篇 湷觥 FC 程式設計
稍加整理去芜存菁,就可以看到这个「程序进入点」主要做些什么事:
int AFXAPI AfxWinMain (HINSTANCE hInstance; HINSTANCE hPrevInstance;
LPTSTR lpCmdLine; int nCmdShow)
{
int nReturnCode = …1;
CWinApp* pApp = AfxGetApp();
AfxWinInit(hInstance; hPrevInstance; lpCmdLine; nCmdShow);
pApp…》InitApplication();
pApp…》InitInstance();
nReturnCode = pApp…》Run();
AfxWinTerm();
return nReturnCode;
}
其中,AfxGetApp 是一个全域函数,定义于AFXWIN1。INL 中:
_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
{ return afxCurrentWinApp; }
而afxCurrentWinApp 又定义于AFXWIN。H 中:
#define afxCurrentWinApp AfxGetModuleState()…》m_pCurrentWinApp
再根据稍早所述CWinApp::CWinApp 中的动作,我们于是知道,AfxGetApp 其实就是取
得CMyWinApp 对象指针。所以,AfxWinMain 中这样的动作:
CWinApp* pApp = AfxGetApp();
pApp…》InitApplication();
pApp…》InitInstance();
nReturnCode = pApp…》Run();
其实就相当于调用:
CMyWinApp::InitApplication();
CMyWinApp::InitInstance();
CMyWinApp::Run();
因而导至调用:
CWinApp::InitApplication(); // 因为 CMyWinApp 并没有改写InitApplication
CMyWinApp::InitInstance(); // 因为 CMyWinApp 改写了 InitInstance
CWinApp::Run(); //因为 CMyWinApp 并没有改写Run
368
…………………………………………………………Page 431……………………………………………………………
第6章 MFC 程式的生死因果
根据第1章SDK 程序设计的经验推测,InitApplication 应该是注册窗口类别的场所?
InitInstance 应该是产生窗口并显示窗口的场所?Run 应该是攫取消息并分派消息的场
所?有对有错!以下数节我将实际带你看看MFC 的源代码,如此一来就可以了解隐藏
在MFC 背后的玄妙了。我的终极目标并不在MFC 源代码(虽然那的确是学习设计一个
application framework 的好教材),我只是想拿把刀子把MFC 看似朦胧的内部运作来个
大解剖,挑出其经脉;有这种扎实的根基,使用MFC 才能知其然并知其所以然。下面小
节分别讨论AfxWinMain 的四个主要动作以及引发的行为。
369
…………………………………………………………Page 432……………………………………………………………
第篇 湷觥 FC 程式設計
AfxWinInit-AFX 内部初始化动作
HELLO。CPP
1 CMyWinApp theApp; // application object
BOOL CMyWinApp::InitInstance()
WINMAIN。CPP
{
int AFXAPI AfxWinMain (。。。) m_pMainWnd = new CMyFrameWnd();
{ m_pMainWnd…》ShowWindow(m_nCmdShow);
CWinApp* pApp = AfxGetApp(); m_pMainWnd…》UpdateWindow();
return TRUE;
2 AfxWinInit(。。。); }
pApp…》InitApplication(); CMyFrameWnd::CMyFrameWnd()
pApp…》InitInstance(); {
nReturnCode = pApp…》Run(); Create(NULL; 〃Hello MFC〃; 。。。;
〃MainMenu〃);
AfxWinTerm(); }
}
void CMyFrameWnd::OnPaint() { 。。。 }
void CMyFrameWnd::OnAbout() { 。。。 }
BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd)
ON_MAND(IDM_ABOUT; OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
我想你已经清楚看到了,AfxWinInit 是继CWinApp 构造式之后的第一个动作。以下是它
的动作摘要(节录自APPINIT。CPP ):
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance; HINSTANCE hPrevInstance;
LPTSTR lpCmdLine; int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
// set resource handles
AFX_MODULE_STATE* pState = AfxGetModuleState();
pState…》m_hCurrentInstanceHandle = hInstance;
pState…》m_hCurrentResourceHandle = hInstance;
// fill in the initial state for the application
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
{
// Windows specific initialization (not done if no CWinApp)
370
…………………………………………………………Page 433……………………………………………………………
第6章 MFC 程式的生死因果
pApp…》m_hInstance = hInstance;
pApp…》m_hPrevInstance = hPrevInstance;
pApp…》m_lpCmdLine = lpCmdLine;
pApp…》m_nCmdShow = nCmdShow;
pApp…》SetCurrentHandles();
}
// initialize thread specific data (for main thread)
if (!afxContextIsDLL)
AfxInitThread();
return TRUE;
}
其中调用的AfxInitThread 函数的动作摘要如下(节录自THRDCORE。CPP ):
void AFXAPI AfxInitThread()
{
if (!afxContextIsDLL)
{
// attempt to make the message queue bigger
for (int cMsg = 96; !SetMessageQueue(cMsg) && (cMsg …= 8); )
;
// set message filter proc
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState…》m_hHookOldMsgFilter == NULL);
pThreadState…》m_hHookOldMsgFilter = ::SetWindowsHookEx(WH_MSGFILTER;
_AfxMsgFilterHook; NULL; ::GetCurrentThreadId());
// intialize CTL3D for this thread
_AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;
if (pCtl3dState…》m_pfnAutoSubclass != NULL)
(*pCtl3dState…》m_pfnAutoSubclass)(AfxGetInstanceHandle());
// allocate thread local _AFX_CTL3D_THREAD just for automatic termination
_AFX_CTL3D_THREAD* pTemp = _afxCtl3dThread;
}
}
如果你曾经看过本书前身Visual C++ 对象导向 MFC 程序设计,我想你可能对这句话
印象深刻:「WinMain 一开始即调用AfxWinInit ,注册四个窗口类别」。这是一个已成
昨日黄花的事实。MFC 的确会为我们注册四个窗口类别,但不再是在AfxWinInit 中完
成。稍后我会把注册动作挖出来,那将是窗口诞生前一刻的行为。
371
…………………………………………………………Page 434……………………………………………………………
第篇 湷觥 FC 程式設計
CWinApp::InitApplication
HELLO。CPP
1 CMyWinApp theApp; // application object
BOOL CMyWinApp::InitInstance()
WINMAIN。CPP
{
int AFXAPI AfxWinMain (。。。) m_pMainWnd = new CMyFrameWnd();
{ m_pMainWnd…》ShowWindow(m_nCmdShow);
CWinApp* pApp = AfxGetApp(); m_pMainWnd…》UpdateWindow();
return TRUE;
2 }
AfxWinInit(。。。);
3 pApp…》InitApplication(); CMyFrameWnd::CMyFrameWnd()
pApp…》InitInstance(); {
nReturnCode = pApp…》Run(); Create(NULL; 〃Hello MFC〃; 。。。;
〃MainMenu〃);
AfxWinTerm(); }
}
void CMyFrameWnd::OnPaint() { 。。。 }
void CMyFrameWnd::OnAbout() { 。。。 }
BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd)
ON_MAND(IDM_ABOUT; OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
AfxWinInit 之后的动作是pApp …》InitApplication 。稍早我说过了,pApp 指向CMyWinApp
对象(也就是本例的theApp ),所以,当程序调用:
pApp…》InitApplication();
相当于调用:
CMyWinApp::InitApplication();
但是你要知道,CMyWinApp 继承自CWinApp,而InitApplication 又是CWinApp 的一个
虚拟函数;我们并没有改写它(大部份情况下不需改写它),所以上述动作相当于调用:
CWinApp::InitApplication();
此函数之源代码出现在APPCORE。CPP 中:
372
…………………………………………………………Page 435……………………………………………………………
第6章 MFC 程式的生死因果
BOOL CWinApp::InitApplication()
{
if (
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!