友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第68部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
break;
case WM_PAINT :
OnPaint(hWnd; wParam; lParam);
break;
default :
DefWindowProc(hWnd; msg; wParam; lParam);
}
}
MFC 程序有新的作法,我们在Hello 程序中也为CMyFrameWnd 准备了两个消息处理
例程,声明如下:
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWnd();
afx_msg void OnPaint();
afx_msg void OnAbout();
DECLARE_MESSAGE_MAP ()
};
OnPaint 处理什么消息?OnAbout 又是处理什么消息?我想你很容易猜到,前者处理
WM_PAINT ,后者处理WM_MAND 的IDM_ABOUT 。这看起来十分俐落,但让人搞
不懂来龙去脉。程序中是不是应该有「把消息和处理函数关联在一起」的设定动作?是
的,这些设定在HELLO。CPP 才看得到。但让我先着一鞭:DECLARE_MESSAGE_MAP
宏与此有关。
362
…………………………………………………………Page 425……………………………………………………………
第6章 MFC 程式的生死因果
这种写法非常奇特,原因是MFC 内建了一个所谓的Message Map 机制,会把消息自动
送到「与消息对映之特定函数」去;消息与处理函数之间的对映关系由程序员指定。
DECLARE_MESSAGE_MAP 另搭配其它宏,就可以很便利地将消息与其处理函数关联
在一起:
BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd)
ON_WM_PAINT()
ON_MAND(IDM_ABOUT; OnAbout)
END_MESSAGE_MAP()
稍后我就来探讨这些神秘的宏。
363
…………………………………………………………Page 426……………………………………………………………
第篇 湷觥 FC 程式設計
引爆器-Application object
我们已经看过HELLO。H 声明的两个类别,现在把目光转到HELLO。CPP 身上。这个档
案将两个类别实作出来,并产生一个所谓的application object 。故事就从这里展开。
下面这张图包括右半部的Hello 源代码与左半部的MFC 源代码。从这一节以降,我将
以此图解释MFC 程序的激活、运行、与结束。不同小节的图将标示出当时的程序进行
状况。
HELLO。CPP
1 CMyWinApp theApp; // application object
BOOL CMyWinApp::InitInstance()
WINMAIN。CPP
{
int AFXAPI AfxWinMain (。。。) m_pMainWnd = new CMyFrameWnd();
int AFXAPI AfxWinMain (。。。)
{{ m_pMainWnd…》ShowWindow(m_nCmdShow);
CWinApp* pApp = AfxGetApp(); m_pMainWnd…》UpdateWindow();
CWinApp* pApp = AfxGetApp();
return TRUE;
AfxWinInit(。。。); }
AfxWinInit(。。。);
pApp…》InitApplication(); CMyFrameWnd::CMyFrameWnd()
pApp…》InitApplication();
pApp…》InitInstance(); {
pApp…》InitInstance();
nReturnCode = pApp…》Run(); Create(NULL; 〃Hello MFC〃; 。。。;
nReturnCode = pApp…》Run();
〃MainMenu〃);
AfxWinTerm(); }
AfxWinTerm();
}}
void CMyFrameWnd::OnPaint() { 。。。 }
void CMyFrameWnd::OnAbout() { 。。。 }
BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd)
ON_MAND(IDM_ABOUT; OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
上图的theApp 就是Hello 程序的application object ,每一个MFC 应用程序都有一个,
而且也只有这么一个。当你执行Hello,这个全域对象产生,于是构造式执行起来。我们
并没有定义CMyWinApp 构造式;至于其父类别CWinApp 的构造式内容摘要如下(摘
录自APPCORE。CPP ):
364
…………………………………………………………Page 427……………………………………………………………
第6章 MFC 程式的生死因果
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
m_pszAppName = lpszAppName;
// initialize CWinThread state
AFX_MODULE_THREAD_STATE* pThreadState = AfxGetModuleThreadState();
pThreadState…》m_pCurrentWinThread = this;
m_hThread = ::GetCurrentThread();
m_nThreadID = ::GetCurrentThreadId();
// initialize CWinApp state
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState…》m_pCurrentWinApp = this;
// in non…running state until WinMain
m_hInstance = NULL;
m_pszHelpFilePath = NULL;
m_pszProfileName = NULL;
m_pszRegistryKey = NULL;
m_pszExeName = NULL;
m_lpCmdLine = NULL;
m_pCmdInfo = NULL;
。。。
}
CWinApp 之中的成员变量将因为theApp 这个全域对象的诞生而获得配置与初值。如果
程序中没有theApp 存在,编译联结还是可以顺利通过,但执行时会出现系统错误消息:
365
…………………………………………………………Page 428……………………………………………………………
第篇 湷觥 FC 程式設計
隐晦不明的 WinMain
HELLO。CPP
1 CMyWinApp theApp; // application object
BOOL CMyWinApp::InitInstance()
WINMAIN。CPP
{
int AFXAPI AfxWinMain (。。。) m_pMainWnd = new CMyFrameWnd();
int AFXAPI AfxWinMain (。。。)
{{ m_pMainWnd…》ShowWindow(m_nCmdShow);
CWinApp* pApp = AfxGetApp(); m_pMainWnd…》UpdateWindow();
CWinApp* pApp = AfxGetApp();
return TRUE;
AfxWinInit(。。。); }
AfxWinInit(。。。);
pApp…》InitApplication(); CMyFrameWnd::CMyFrameWnd()
pApp…》InitApplication();
pApp…》InitInstance(); {
pApp…》InitInstance();
nReturnCode = pApp…》Run(); Create(NULL; 〃Hello MFC〃; 。。。;
nReturnCode = pApp…》Run();
〃MainMenu〃);
AfxWinTerm(); }
AfxWinTerm();
}
}
void CMyFrameWnd::OnPaint() { 。。。 }
void CMyFrameWnd::OnAbout() { 。。。 }
BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd)
ON_MAND(IDM_ABOUT; OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
theApp 配置完成后,WinMain 登场。我们并未撰写WinMain 程序代码,这是MFC 早已
准备好并由联结器直接加到应用程序代码中的,其源代码列于图6…4 。_tWinMain 函数的
! §…t! ¨ 是为了支持Unicode 而准备的一个宏。
// in APPMODUL。CPP
extern 〃C〃 int WINAPI
_tWinMain (HINSTANCE hInstance; HINSTANCE hPrevInstance;
LPTSTR lpCmdLine; int nCmdShow)
{
// call shared/exported WinMain
return AfxWinMain (hInstance; hPrevInstance; lpCmdLine; nCmdShow);
}
此外,在DLLMODUL。CPP 中有一个DllMain 函数。本书并未涵盖DLL 程序设计。
366
…………………………………………………………Page 429……………………………………………………………
第6章 MFC 程式的生死因果
// in WINMAIN。CPP
#0001 /////////////////////////////////////////////////////////////////
#0002 // Standard WinMain implementation
#0003 // Can be replaced as long as 'AfxWinInit' is called first
#0004
#0005 int AFXAPI AfxWinMain (HINSTANCE hInstance; HINSTANCE hPrevInstance;
#0006 LPTSTR lpCmdLine; int nCmdShow)
#0007 {
#0008 ASSERT(hPrevInstance == NULL);
#0009
#0010 int nReturnCode = …1;
#0011 CWinApp* pApp = AfxGetApp();
#0012
#0013 // AFX internal initialization
#0014 if (!AfxWinInit(hInstance; hPrevInstance; lpCmdLine; nCmdShow))
#0015 goto InitFailure;
#0016
#0017 // App global initializations (rare)
#0018 ASSERT_VALID(pApp);
#0019 if (!pApp…》InitApplication())
#0020 goto InitFailure;
#0021 ASSERT_VALID(pApp);
#0022
#0023 // Perform specific initializations
#0024 if (!pApp…》InitInstance())
#0025 {
#0026 if (pApp…》m_pMainWnd != NULL)
#0027 {
#0028 TRACE0(〃Warning: Destroying non…NULL m_pMainWndn〃);
#0029 pApp…》m_pMainWnd…》DestroyWindow();
#0030 }
#0031 nReturnCode = pApp…》ExitInstance();
#0032 goto InitFailure;
#0033 }
#0034 ASSERT_VALID(pApp);
#0035
#0036 nReturnCode = pApp…》Run();
#0037 ASSERT_VALID(pApp);
#0038
#0039 InitFailure:
#0040
#0041 AfxWinTerm();
#0042 return nReturnCode;
#0043 }
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!