设为首页 加入收藏

TOP

MFC应用程序框架入门(二)
2012-11-04 15:21:56 来源: 作者: 【 】 浏览:613
Tags:MFC 应用程序 框架 入门


  2 MFC对API函数的封装

  如果读者曾经有过SDK的开发经历,一定会对其烦琐的编程(www.cppentry.com)方式和大量的Win32 API函数调用深有感触。所有不同功能的API函数均是以全局函数的形式放在一起的,由于API函数数目比较庞大,因此无论是学习还是使用都是有一定难度的。相比而言,建立在API函数基础之上的MFC类库则通过把相关API函数的分类封装而可以大大简化编程(www.cppentry.com)的难度,用MFC类编写的Windows 应用程序完成相同的任务只需要进行少量的工作。

  众多的API函数根据功能的不同而被MFC封装到200多个类中,这些类基本涵盖了进行Windows 编程(www.cppentry.com)大部分可能用到的功能。由于封装后的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编程(www.cppentry.com)中使用相当不便的窗口处理函数,是消息的分发处理更加方便。

  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);
}

  可以看出,主要工作是在CreateEx()成员函数中完成的,而该函数又是对API函数CreateWindowEx()的封装。封装后的代码在调用CreateWindowEx()前构造并填充了一个非常类似于WNDCLASS结构的CREATESTRUCT结构,并调用了PreCreateWindow()。

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;
}

  看上去经过封装的窗口创建函数要比原API函数复杂许多,但这并不说明MFC的封装将导致编程(www.cppentry.com)的效率低下,恰恰相反,由于CWnd在绝大多数场合中是以基类的形式出现的,因此可在派生类中添加代码完成对CWnd::Create()的调用而比较方便的实现对派生类窗口的创建。

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇虚拟内存技术原理和使用方法 下一篇VC++.NET OpenGL编程快速入门

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: