函数名 | 函数说明 |
AfxAbout | 无条件终止一个应用程序;通常在发生无法回复的错误时使用 |
AfxBeginThread | 创建一个新的线程并开始执行 |
AfxEndThread | 终止当前正在执行的线程 |
AfxMessageBox | 显示一个Windows 消息窗口 |
AfxGetApp | 返回一个指向应用程序对象的指针 |
AfxGetAppName | 返回应用程序名 |
AfxGetMainWnd | 返回一个指向应用程序主窗口的指针 |
AfxGetInstanceHandle | 返回一个标识当前应用程序实例的句柄 |
AfxRegisterWndClass | 为一个MFC应用程序注册一个用户自定义的窗口类 |
2 MFC对API函数的封装
如果读者曾经有过SDK的开发经历,一定会对其烦琐的编程方式和大量的Win32 API函数调用深有感触。所有不同功能的API函数均是以全局函数的形式放在一起的,由于API函数数目比较庞大,因此无论是学习还是使用都是有一定难度的。相比而言,建立在API函数基础之上的MFC类库则通过把相关API函数的分类封装而可以大大简化编程的难度,用MFC类编写的Windows 应用程序完成相同的任务只需要进行少量的工作。
众多的API函数根据功能的不同而被MFC封装到200多个类中,这些类基本涵盖了进行Windows 编程大部分可能用到的功能。由于封装后的MFC类太多,这里不能一一介绍,下面就以其中比较重要的CObject类和CWnd类为例对API函数的封装情况做一简要介绍。
CObject类是MFC中最主要也是最基本的类之一,该类不支持多重继承,派生的类只能有一个CObject基类。CObject类是位于类层次结构最顶层的,绝大多数MFC类都是从CObject类派生出来的。CObject类包含了所有MFC类必须具备的几个基本功能:持久性支持、运行时类信息支持和诊断调试支持。其中持久性支持功能由成员函数IsSerializable()和Serialize()提供。前者用于检测对象是否支持序列化。如果一个类能够被序列化,就必须在声明时包含DECLARE_SERIAL宏、在实现时包含IMPLEMENT_SERIAL宏。Serialize()函数则可以将对象写入档案文件(Archive)或从档案文件读出对象。成员函数GetRuntimeClass()可以获取到一个指向CruntimeClass类对象的指针,通过该指针可以得到对象的运行时类信息。CObject类在诊断调试支持方面提供了成员函数AssertValid()和Dump(),前者可对对象内存状态的有效性进行检查,后者负责将对象的内容转储到一个CdumpContext对象中,并可以提供诊断服务及一些有用的调试信息。
在MFC中,CWnd类提供了所有窗口类的基本功能,是一个非常重要的类,大约三分之一的MFC类都是以此为基类。该类主要对创建、操纵窗口类的API函数进行了封装,而且通过消息映射机制隐藏了SDK编程中使用相当不便的窗口处理函数,是消息的分发处理更加方便。
CWnd类最重要的一个封装是对API函数CreateWindow()的封装,该函数被封装为CWnd类成员函数Create()。从VC提供的MFC源文件WinCore.cpp中可以清楚看出CWnd类对CreateWindow()函数的封装过程,下面给出相关部分的实现清单:
BOOL CWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // can't use for desktop or pop-up windows (use CreateEx instead) ASSERT(pParentWnd != NULL); ASSERT((dwStyle & WS_POPUP) == 0); return CreateEx(0, lpszClassName, lpszWindowName, dwStyle | WS_CHILD, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext); } |
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; if (!PreCreateWindow(cs)) { PostNcDestroy(); return FALSE; } AfxHookWindowCreate(this); HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); #ifdef _DEBUG if (hWnd == NULL) { TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X\n", GetLastError()); } #endif if (!AfxUnhookWindowCreate()) PostNcDestroy(); // cleanup if CreateWindowEx fails too soon if (hWnd == NULL) return FALSE; ASSERT(hWnd == m_hWnd); // should have been set in send msg hook return TRUE; } |
3 MFC应用程序框架
MFC应用程序框架可以看作是MFC基本类库的一个超集(Superset),类库是众多可在任何程序中使用的类的集合,而应用程序框架则定义了程序自身的结构。下面给出一个使用了MFC应用程序框架的简单例子,通过这段例程可以比较清楚地了解MFC应用程序框架的一般结构。
// Sample01.h文件 // 应用程序类 class CSample01App : public CWinApp { public: virtual BOOL InitInstance(); }; // 框架窗口类 class CSample01Frame : public CFrameWnd { public: CSample01Frame(); protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; // Sample01.cpp文件 #include <afxwin.h> #include "Sample01.h" // 应用程序对象 CSample01App theApp; // 初始化应用程序实例 BOOL CSample01App::InitInstance() { m_pMainWnd = new CSample01Frame(); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } // 消息映射 BEGIN_MESSAGE_MAP(CSample01Frame, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() // 构造函数 CSample01Frame::CSample01Frame() { Create(NULL, "MFC应用程序框架程序"); } // WM_PAINT消息响应函数 void CSample01Frame::OnPaint() { CPaintDC dc(this); dc.TextOut(100, 100, "Hello World!"); } |