按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
};
熟悉Win32 的朋友,看到CWinThread 类别之中的SuspendThread 和ResumeThread 成
员函数,可能会发出会心微笑。
361
…………………………………………………………Page 424……………………………………………………………
第篇 湷觥 FC 程式設計
CFrameWnd -取代 WndProc 的地位
CFrameWnd 主要用来掌握一个窗口,几乎你可以说它是用来取代SDK 程序中的窗口函
式的地位。传统的SDK 窗口函数写法是:
long FAR PASCAL WndProc(HWND hWnd; UNIT msg; WORD wParam; LONG lParam)
{
switch(msg) {
case WM_MAND :
switch(wParam) {
case IDM_ABOUT :
OnAbout(hWnd; wParam; lParam);
break;
}
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();