mfc程序开发参考大全,MFC框架
本文主要介绍了VC 6.0的MFC编程方法和MFC应用框架。
关键词:VC 6.0MFC程序框架
1 MFC概述
顾明思一、MFC应用框架是基于MFC的,这种框架模式构建的应用在程序结构和组织上与以前的Win32 SDK编程模式完全不同。自上世纪90年代初出现以来,MFC一直试图将Windows API函数封装到类库中的每个逻辑类中。MFC的这种封装不是简单的将API函数分组打包,更多的是试图通过类来实现所有的系统策略。随着越来越多系统功能的加入,MFC的规模也在不断扩大。目前MFC已经有200多个类,涵盖了一般Windows类、文档/可视化框架、OLE、数据库、互联网、分布式函数的基本内容。如此扎实的程序开发基础无疑在很大程度上方便了程序员开发Windows程序。
MFC提供了相当多的具有不同功能的类来适应尽可能广泛的需求。这里的大多数MFC类都是直接或间接从CObject类派生而来的。CObject类为其派生类提供了三个重要特性:持久性(序列化)支持、运行时类信息支持和诊断调试支持。其中,持久化是将一个类对象中的持久化数据以流的形式导出或导入到磁盘文件等外部存储介质中的过程;运行时类信息(RTCI)可以在运行时检索对象的类名和关于该对象的其他信息。RTCI是C语言中除了运行时类型信息机制(RTTI)之外的另一个重要工具。作为CObject类的一个组件,诊断和调试支持可以在实现CObject派生类时执行有效性检查,并将状态信息输出到调试窗口。
MFC提供的函数并不都是类成员函数,MFC还提供了一系列前缀为Afx的全局函数。类函数只能在所属类对象的上下文中使用,但是这些AFX函数可以随时随地直接使用。下表列出了几个重要的AFX函数:2 API函数的MFC封装
如果读者曾经经历过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()函数可以向归档文件中写入对象或从中读取对象。GetRuntimeClass()函数可以获得一个指向CruntimeClass类对象的指针,通过这个指针可以获得对象的运行时类信息。CObject类提供了成员函数AssertValid()和Dump(),用于诊断和调试支持。前者可以检查对象内存状态的有效性,而后者负责将对象的内容转储到CdumpContext对象中,并可以提供诊断服务和一些有用的调试信息。
在MFC中,CWnd类提供了所有窗口类的基本功能,是一个非常重要的类。大约三分之一的MFC类基于它。该类主要封装了创建和操作窗口类的API函数,通过消息映射机制隐藏了SDK编程中不方便使用的窗口处理函数,使得消息的分发和处理更加方便。
CWnd类最重要的封装是API函数CreateWindow()的封装,封装为CWnd类成员函数Create()。从VC提供的MFC源文件WinCore.cpp中可以明显看出,CWnd类封装了CreateWindow()函数。下面是相关部分的实现列表:boolcwnd: create (lpctstr lpsz类名,lpctstr lpsz窗口名,DWORD dwStyle,const RECT rect,CWnd* pParentWnd,UINT nID,CCreateContext* pContext)
{
//不能用于桌面或弹出窗口(改用CreateEx)
ASSERT(pParentWnd!=NULL);
ASSERT((dw style WS _ POPUP)==0);
返回CreateEx(0,lpszClassName,lpszWindowName,dwStyle WS_CHILD,rect.left,rect.top,rect.right - rect.left,rect.bottom - rect.top,pParentWnd- GetSafeHwnd(),(HMENU)nID,(LPVOID)p context);
}
可以看出,主要工作是在CreateEx()成员函数中完成的,该函数封装了API函数CreateWindowEx()。封装的代码在调用CreateWindowEx()之前构造并填充一个与WNDCLASS结构非常相似的CREATESTRUCT结构,并调用PreCreateWindow()。BOOL CWnd:CreateEx(DWORD dwex style,LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,int x,int y,int nWidth,int nHeight,HWND hWndParent,HMENU nIDorHMenu,LPVOID lpParam)
{
//允许修改几个常见的创建参数
创建结构化cs;
cs . dwex style=dwex style;
cs . lpsz class=lpsz class name;
cs.lpszName=lpszWindowName
cs.style=dwStyle
cs.x=x
cs.y=y
cs.cx=nWidth
cs.cy=nHeight
cs . hwnd parent=hwnd parent;
cs . hm enu=nIDorHMenu;
cs . h instance=AfxGetInstanceHandle();
cs.lpCreateParams=lpParam
如果(!预创建窗口(cs))
{
post ncdestroy();
返回FALSE
}
AfxHookWindowCreate(this);
HWND HWND=:CreateWindowEx(cs . dwex style,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(警告:窗口创建失败:GetLastError返回0x%8.8Xn ,GetLastError());
}
#endif
如果(!AfxUnhookWindowCreate())
post ncdestroy();//如果CreateWindowEx过早失败,则清除
if (hWnd==NULL)
返回FALSE
ASSERT(hWnd==m _ hWnd);//应该已经在发送消息挂钩中设置
返回TRUE
}
封装后的窗口创建函数看似比原来的API函数复杂很多,但并不意味着MFC的封装会导致编程的低效。相反,因为CWnd在大多数情况下是以基类的形式出现的,所以可以在派生类中添加代码来完成对CWnd:Create()的调用,这样更容易创建派生类窗口。
3 MFC应用程序框架
MFC应用框架可以看作是MFC基本类库的一个超集,基本类库是可以在任何程序中使用的许多类的集合,而应用框架定义了程序本身的结构。下面是一个使用MFC应用程序框架的简单例子。通过这个例程,我们可以清楚地了解MFC应用程序框架的一般结构。//Sample01.h文件
//应用程序类
类CSample01App:公共CWinApp
{
公共:
虚拟BOOL InitInstance();
};
//框架窗口类
类CSample01Frame : public CFrameWnd
{
公共:
c sample 01 frame();
受保护:
afx _ msg void OnPaint();
声明消息映射()
};
//Sample01.cpp文件
#包含afxwin.h
#include Sample01.h
//应用程序对象
c sample 01 app the app;
//初始化应用程序实例
BOOL CSample01App:InitInstance()
{
m _ pMainWnd=new c sample 01 frame();
m _ pMainWnd-show window(m _ nCmdShow);
m _ pMainWnd-update window();
返回TRUE
}
//消息映射
BEGIN _ MESSAGE _ MAP(c sample 01 frame,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
//构造函数
CSample01Frame:CSample01Frame()
{
Create(NULL,“MFC应用程序框架”);
}
//WM_PAINT消息响应函数
void CSample01Frame:OnPaint()
{
CPaintDC dc(这个);
华盛顿。TextOut(100,100,你好,世界!);
}
像编写Sample00程序一样建立一个Win32应用程序项目Sample01(匹配程序见 CD-ROM Matching Program sample 01 ),然后分别在项目中添加头文件Sample01.h和源文件Sample01.cpp,将上述代码写入相应的文件中。为了顺利编译,需要修改编译命令,通过 Alt F7 快捷键调出[项目设置]对话框,在[预处理程序定义]列的末尾添加选项 _AFXDLL ,前面用逗号隔开。接下来,您需要在[Project Options]列的末尾添加命令行/MD ,用空格与其他命令行参数隔开。编译后可以看到效果和SDK编写的Sample00程序一样,只是代码实现更结构化,编写过程更简单。
接下来,分析上面的应用框架代码。首先说一下MFC应用的核心——csample 01 app,它是- CWinApp类的派生类。CWinApp类提供了一个消息循环和一些关键的虚函数,这些虚函数可以获取消息并将它们分发到应用程序窗口。通过重载这些虚函数,开发人员可以扩展应用程序的一些固有行为。当头文件Afxwin.h包含在内时,程序中可以使用包括CWinApp在内的一些MFC类。一个MFC应用程序有并且只能有一个application对象,并且必须是全局声明的,所以这个对象从程序开始运行就一直驻留在内存中。
因为使用MFC应用框架的程序本质上还是一个Windows应用,所以在程序中需要有WinMain()函数作为Windows应用的入口。WinMain()函数之所以在前面的示例代码中看不到,是因为它已经通过封装隐藏在应用程序框架中了。除了WinMain(),CWinApp类成员函数Run()也被隐式执行。这个功能也很重要。它负责将消息放入应用程序窗口的消息循环中,WinMain()函数完成对Run()的调用。当WinMain()函数找到应用对象后,会立即调用CWinApp类的虚函数InitInstance()。因为CWINAP的基类不知道需要什么样的主框架窗口,所以必须在CWINAP的派生类中重载InitInstance()函数。当应用程序已经开始运行但窗口还没有创建时,调用InitInstance()函数。如果窗口不是由InitInstance()创建的,应用程序就不能拥有窗口,也就意味着没有InitInstance()函数的应用程序就不能接收和处理消息,也就失去了对Windows程序的意义。所以从CWinApp类派生,重载InitInstance()函数是编写MFC应用框架的必要条件。
除了application类,从CFrameWnd派生的CSample01Frame类也描述了应用程序的主框架窗口。在构造函数中调用基类的CFrameWnd成员函数Create()。Windows负责创建实际的窗口结构,应用程序框架将其链接到C对象。
这个示例程序的大部分功能实际上都是在MFC的CWinApp、CFrameWnd等基类中完成的。编程时,只需要在派生类中编写少量的函数代码。c允许以这种方式从基类借用大量代码,而无需复制代码。应用框架负责提供者的结构框架,开发者在上面添加相应的实现代码,就可以非常方便地完成一个完整的应用。应用框架不仅定义了应用的结构,实际上还包含了更多的C基类。
4摘要
SDK的API编程方法、MFC的编程方法以及本系列讲座后面要介绍的ATL编程方法是VC编程中常用的几种编程方法,其中MFC由于功能强大、编程方式灵活,是大多数程序开发人员最常使用的编程方法。本文从基本问题出发,详细论述了MFC及其框架程序,使读者对MFC编程有一个基本的了解。