到现在,相信您不仅知道框架程序的使用方法,还非常清楚它的内部实现。下面将直接介绍如何在微软的基础类库MFC中创建窗口应用程序。
MFC(Microsoft Fundation Classes,Microsoft基础类库)使用C++类对Windows API进行封装,较大程度地屏蔽了Windows编程的复杂性,使得Windows应用程序的设计变得简单。这是大多数软件开发者使用的一个类库。
以上一节的06Meminfo程序为例,看看如何在MFC下编译这些程序。具体步骤如下:
(1)包含头文件。打开06Meminfo工程,将Meminfo.h文件中包含头文件的代码改为:
#include "afxwin.h" // 原先此处的代码为“#include "../common/_afxwin.h"”
也就是把包含我们类库的文件的代码全改为包含MFC中文件的代码。文件名称也是对应的,只要将前缀“_”去掉即可。
(2)清除工程中原类库文件。将从COMMON文件夹下添加到工程中的文件全部删除 (从VC工程中删除)。这时工程中只有Meminfo.h和Meminfo.cpp两个文件。现在通过菜单命令“Build/Rebuild All”全部重新编译连接程序。
(3)修改工程设置。如果出现连接错误的话,还要对工程进行的设置。单击菜单命令“Project/Settings…”,打开设置工程属性的对话框,切换到General选项卡,在Microsoft Foundation Classes窗口下选中Use MFC in a Static Library选项,如图6.6所示。单击OK按钮即可。
第3步指定了如何链接到MFC。Microsoft Foundation Classes窗口下共有3个选项:
Not Using MFC 不使用MFC
Use MFC in a Static Library 静态链接到MFC。这样最终生成的程序不依赖MFC运行期库也能 够运行。一般在发布程序时,要设置这个选项
Use MFC in a Shared DLL 动态链接到MFC。这样最终生产的程序要依赖MFC运行期库才能 够运行
在工程中使用MFC是非常简单的,只要按照第3步的方法修改工程设置,然后包含上定义要使用的类的文件即可。以前所设计的类的命名方式和MFC的命名方式是相同的,它们所提供的接口也完全相同。所以,本书所有使用框架程序的例子都可以在MFC下编译通过。
MFC把大多数API函数都封装成了类,以方便用户的使用。比如,它把操作设备环境的函数都封装到了CDC类中,此类一个公开成员变量m_hDC,保存了与CDC对象关联的设备环境的句柄。为了方便响应WM_PAINT消息、操作窗口客户区、操作整个窗口,MFC又从CDC类派生了CPaintDC、CClientDC 和CWindowDC类。下面是CPaintDC类的简化版本:
class CPaintDC : public CDC
{
public:
CPaintDC(CWnd* pWnd);
~CPaintDC();
protected:
HWND m_hWnd;
PAINTSTRUCT m_ps;
};
CPaintDC::CPaintDC(CWnd* pWnd)
{
m_hWnd = pWnd->GetSafeHwnd();
Attach(::BeginPaint(m_hWnd, &m_ps)); // Attach函数将设置返回句柄与CPaintDC对象的关联
}
CPaintDC::~CPaintDC()
{
::EndPaint(m_hWnd, &m_ps);
}
程序在实例化CPaintDC对象时调用了BeginPaint函数,当在销毁这个对象时又调用了EndPaint函数。以后就可以这样响应WM_PAINT消息了:
void CMainWindow::OnPaint()
{
CPaintDC dc(this);
//…… // 其他代码
}
另外两个类的实现过程与CPaintDC类相似,CClientDC的构造函数取得窗口客户区的设备环境句柄,CWindowDC类取得整个窗口的设备环境句柄。
对MFC的讨论绝不仅仅是这些,但核心的功能已经完全模拟实现了,剩下的都是一些固定的使用格式。本书附录1列出了整个MFC 6.0的层次结构。下一小节将使用MFC创建一个窗口信息查看程序,以更深切地感受MFC的工作方式。