微软MFC技术简明介绍

微软技术分享 微软最有价值专家
全栈领域优质创作者
博客专家认证
2024-02-12 09:44:24

我是荔园微风,作为一名在IT界整整25年的老兵,今天来看一下微软MFC技术简明介绍

Visual C++ 与 MFC

微软公司于1992年上半年推出了C/C++ 7.0 产品时初次向世人介绍了MFC 1.0,这个产品包含了20,000行C++原始代码,60个以上的Windows相关类,以及其它的一般类如时间、数据处理、文件、内存、诊断、字符串等等等。它所提供的,其实是一个 "thin and efficient C++ transformation of the Windows API"。其32位版亦在1992年下半年随着 Win32 SDK 推出。

MFC 1.0 获得的回响带给 AFX 小组不少鼓舞。他们的下一个目标放在更高阶的架构支持和组件用户接口上。前者成就了Document/View 架构,后者成就了工具栏、状态栏、打印、预览等极受欢迎的UI性质。当然,他们并没有忘记兼容性与移植性。虽然 AFX 小组并未承诺MFC可以跨不同操作系统如 UNIX XWindow、OS/2 PM、Mac System 7,但在其本家(Windows 产品线)身上,在16位Windows 3.x和32位Windows 95 与Windows NT之间的移植性是无庸置疑的。虽然其16位产品和32位产品是分别包装销售,你的原始代码通常只需重新编译链接即可。

Visual C++ 1.0(也就是 C/C++ 8.0)搭配 MFC 2.0 于1993/03 推出,这是针对Windows 3.x 的16位产品。接下来又在1993/08 推出在Windows NT上的 Visual C++ 1.1 for Windows NT,搭配的是MFC 2.1。这两个版本有着相同的基本性质。MFC 2.0 内含近60,000 行 C++ 程序代码,分散在 100 个以上的类中。Visual C++ 整合环境的数个重要工具(如Wizards)本身即以 MFC 2.0 设计完成,它们的出现对于软件生产效率的提升有极大贡献。

微软在 1993年又推出了 16 位的 Visual C++ 1.5,搭配 MFC 2.5。这个版本最大的进步是多了 OLE2 和 ODBC 两组类。整合环境也为了支持这两组类而做了些微改变。

1994年,微软推出Visual C++ 2.0,搭配MFC 3.0,这个32位版本主要的特征在于配合目标操作系统(Windows NT 和Windows 95),支持多线程。所有类都是thread-safe。UI 对象方面,加入了属性表(Property Sheet)、miniframe 窗口、可随处停驻的工具栏。MFC collections 类改良为 template-based。链接器有重大突破,原使用的Segmented Executable Linker 改为 Incremental Linker,这种链接器在对 OBJ 文件做链接时,并不每次从头到尾重新来过,而只是把新数据往后加,旧数据加记作废。想当然耳,EXE 文件会累积许多不用的垃圾,那没关系, 透过Win32 memory-mapped file, 操作系统(Windows NT 及 Windows 95)只把欲使用的部分加载,丝毫不影响执行速度。

1995年,微软又加上了MAPI(Messaging API)和 WinSock 支持,推出 MFC 3.1(32 位元版),并供应13个通用控制组件,也就是 Windows 95 所提供的tree、tooltip、spin、slider、progress、RTF edit 等等控制组件。

1995年,MFC 有了3.2 版,那是不值一提的小改版。

然后就是1995年的32 位MFC 4.0。这个版本纳入了DAO 数据库类、多线程同步控制类,并允许制作 OCX containers。搭配推出的 Visual C++ 4.0 编译器,也终于支持了 template、RTTI 等 C++ 语言特性。IDE 整合环境有重大的改头换面行动,Class View、Resource View、File View 都使得项目的管理更直觉更轻松,Wizardbar 则活脱脱是一个简化的ClassWizard。此外,多了一个极好用的Components Gallery,并允许程序员订制AppWizard。

1996 年上半年又推出了MFC 4.1,最大的焦点在ISAPI(Internet Server API)的支持,提供五个新类 , 分别是CHttpServer 、CHttpFilter 、 CHttpServerContext 、CHttpFilterContext、CHtmlStream,用以建立交互式 Web 应用程序。整合环境方面也对应地提供了一个ISAPI Extension Wizard。在附加价值上,Visual C++ 4.1提供了Game SDK,帮助开发Windows 95上的高效率游戏软件。Visual C++ 4.1 还提供不少个由协力公司完成的OLE控制组件(OCXs),这些 OLE 控制组件技术很快就要全面由桌上跃到网上,称为 ActiveX 控制组件。不过,遗憾的是,Visual C++ 4.1 的编译器有些臭虫,不能够制作 VxD(虚拟装置驱动程序)。

1996 年下半年推出的 MFC 4.2,提供对 ActiveX 更多的技术支持,并整合 Standard C++ Library。它封包一组新的 Win32 Internet 类(统称为 WinInet),使 Internet 上的程序开发更容易。它提供 22 个新类和 40 个以上的新成员函数。它也提供一些控制元件,可以系结(binding)近端和远程的数据源(data sources)。整合环境方面,Visual C++ 4.2提供新的Wizard给ActiveX 程序开发使用,改善了影像编辑器,使它能够处理在Web 服务器上的两个标准图文件格式:GIF 和 JPEG。

1997 年推出的Visual C++ 5.0,主要诉求在编译器的速度改善,并将Visual C++ 合并到微软整个Visual Tools的终极管理软件Visual Studio 97 之中。所有的微软虚拟开发工具,包括 Visual C++、Visual Basic、Visual J++、Visual InterDev、Visual FoxPro、都在Visual Studio 97 的整合之下有更密切的彼此奥援。至于程序设计方面,MFC 本身没有什么变化(4.21 版),但附了一个 ATL(Active Template Library)2.1 版,使 ActiveX 控制组件的开发更轻松些。

我想你会发现,微软正不断地为为什么要使用MFC加上各式各样的强烈理由,并强烈导引它成为Windows 程序设计的 C++ 标准接口。你会看到愈来愈多的 MFC/C++ 程序代码。

MFC概况

MFC非常巨大(其它application framework也不差),MFC 类主要可分为下列数大群组:

  • General Purpose classes——提供字符串类、数据处理类(如数组与串列),异常情况处理类、文件类...等等。
  • Windows API classes - 用来封包Windows API,例如窗口类、对话框类、DC 类...等等。
  • Application framework classes——组成应用程序骨干者,即此组类,包括Document/View、消息捕获、消息映射、消息循环、动态生成、文件读写等等。
  • High level abstractions - 包括工具栏、状态栏、分裂窗口、卷动窗口等等。
  • operation system extensions - 包括OLE、ODBC、DAO、MAPI、WinSock、ISAPI等等。

General Purpose classes

也许你使用 MFC 的第一个目标是为了写 Windows 程序,但并不是整个 MFC 都只为此目的而被发明出来。下面这些类适用于 Windows,也适用于 DOS。

CObject

绝大部分类库,往往以一个或两个类,做为其它绝大部分类的基础。MFC 亦复如此。CObject是万类之首,凡类派生自CObject者,得以继承数个面向对象重要性质,包括RTTI(运行时期类型识别)、Persistence(对象保存)、Dynamic Creation(动态生成)、Diagnostic(错误诊断)。

数据处理类(collection classes)

所谓collection,意指用来管理一群对象或标准类型的数据。这些类像是Array或List 或 Map 等等,都内含针对元素的加入或删除或巡访等成员函数。Array (数组)和 List(串列)是数据结构这门课程的重头戏,大家比较熟知,Map(可视之为表格)则是由成双成对的两两对象所构成,使你很容易由某一对象得知成对的另一对象;换句话说一个对象是另一个对象的键值(key)。例如,你可以使用 String-to-String Map,管理一个电话-人名数据库;或者使用 Word-to-Ptr Map,以 16 位数值做为一个指针的键值。

最令人侧目的是,由于这些类都支持 Serialization,一整个数组或串列或表格可以单一一进程序代码就写到文件中(或从文件读出)。

MFC 支持的collection classes有:

https://img-blog.csdnimg.cn/img_convert/ec04d98b83fc027817a6fe4441e1e6e6.jpeg

杂项类

  • Crect——封装Windows 的RECT 结构。这个类在Windows环境中特别有用,因为CRect常常被用作MFC类成员函数的参数。
  • Csize——封装Windows的SIZE结构。
  • Cpoint——封装Windows的POINT 结构。这个类在Windows环境中特别有用,因为CPoint常常被用作MFC类成员函数的参数。
  • Ctime——表现绝对时间,提供许多成员函数,包括取得目前时间 ( static GetCurrentTime)、将时间数据格式化、抽取特定字段(时、分、秒)等等。它对于 +、-、+=、-+ 等运算符都做了重载动作。
  • CtimeSpan——以秒数表现时间,通常用于计时秒表。提供许多成员函数,包括把秒数转换为日、时、分、秒等等。
  • Cstring——用来处理字符串。支持标准的运算符如 =、+=、< 和 >。

异常处理类(exception handling classes)

所谓异常情况(exception),是发生在你的程序运行时期的不正常情况,像是文件打不开、内存不足、写入失败等等等。与异常处理有关的MFC类一共有以下11种:

https://img-blog.csdnimg.cn/img_convert/0a5be99e0343d68d44c61be0dec8a3b6.jpeg

Windows API classes

这是MFC声名最大的一群类。如果你去看看原始代码,就会看到这些类的成员函数所对应的各个Windows API函数。

  • CwinThread——代表MFC程序中的一个线程。自从3.0 版之后,所有的MFC类就都已经是thread-safe了。SDK 程序中标准的消息循环已经被封装在此一类之中(你会在第6章看到我如何把这一部分开膛剖肚)。
  • CwinApp——代表你的整个MFC应用程序。此类派生自CWinThread;要知道,任何32位Windows程序至少由一个线程构成。CWinApp 内含有用的成员变 数 如 m_szExeName,放置执行文件文件名 ,以及有用的成员函数如ProcessShellCommand,处理命令列选项。
  • CWnd——所有窗口,不论是框架窗口、子框窗口、对话框、控制组件、view 窗口,都有一个对应的C++ 类,你可以想象窗口handle和C++ 对象结盟。这些C++ 类统统派生自 CWnd,也就是说,凡派生自 CWnd 之类才能收到 WM_ 窗口消息(WM_COMMAND 除外)。 所谓窗口handle和C++ 对象结盟,实际上是CWnd 对象有一个成员变量m_hWnd,就放着对应的窗口handle。所以,只要你手上有一个CWnd 对象或CWnd 对象指针,就可以轻易获得其窗口handle:
    ```bash
    HWND hWnd = pWnd->m_hWnd;
  
+  CcmdTarget——CWnd的父类。派生自它 ,类才能够处理命令消息WM_COMMAND。这个类是消息映射以及命令消息循环的大部分关键。  
+  GDI 类、DC 类、Menu 类。  


### Application framework classes


这一部分最为人认知的便是Document/View,这也是使MFC跻身 application framework的关键。Document/View 的观念是希望把数据的本体,和数据的显示分开处理。由于文件产生之际,必须动态生成 Document/View/Frame 三种对象,所以又必须有所谓的Document Template 管理之。

CDocTemplate、CSingleDocTemplate、CmultiDocTemplate——Document Template 扮演黏胶的角色,把 Document 和 View 和其 Frame(外框窗口)胶黏在一块儿。CSingleDocTemplate 一次只支持一种文件类型,CMultiDocTemplate 可同时支持多种文件类型。注意,这和 MDI 程序或 SDI 程序无关,换句话说,MDI 程序也可以使用CSingleDocTemplate,SDI 程序也可以使用CMultiDocTemplate。

但是,逐渐地,MDI 这个字眼与它原来的意义有了一些出入(要知道,这个字眼早在SDK时代即有了)。因此,你可能会看到有些书籍这么说:MDI 程序使用CMultiDocTemplate,SDI程序使用CSingleDocTemplate。

Cdocument——当你为自己的程序由CDocument 派生出一个子类后,应该在其中加上成员变量,以容纳文件数据;并加上成员函数,负责修改文件内容以及

读写文件。读写文件由虚函数Serialize 负责。

Cview——此类负责将文件内容呈现到显示装置上:也许是屏幕,也许是打印机。文件内容的呈现由虚函数OnDraw负责。由于这个类实际上就是你在屏幕上所看到的窗口(外再罩一个外框窗口),所以它也负责用户输入的第一线服务。

### High level abstractions


视觉性UI对象属于此类,例如工具栏CToolBar、状态栏CStatusBar、对话框列CDialogBar。加强型的View也属此类,如可卷动的ScrollView、以对话框为基础的CFormView、小型文字编辑器CEditView、树状结构的CTreeView,支持RTF文件格式的CRichEditView 等等。

### Afx 全局函数


还记得吧,C++ 并不是纯种的面向对象语言(SmallTalk 和Java才是)。所以,MFC之中得以存在有不属于任何类的全局函数,它们统统在函数名称开头冠以Afx。

下面是几个常见的 Afx 全局函数:

```bash
函数名称                               说明

https://img-blog.csdnimg.cn/img_convert/f37921f0ab2084834147cb35f87847b6.jpeg

MFC宏(macros)

CObject和CRuntimeClass之中封装了数个所谓的object services,包括取得运行时期的类信息(RTTI)、Serialization(文件读写)、动态产生对象...等等。所有派生自CObject的类,都继承这些机能。

取得运行时期的类信息(RTTI),使你能够决定一个运行时期的对象的类信息,这样的能力在你需要对函数参数做一些额外的类型检验,或是当你要针对对象属于某种类而做特别的动作时,份外有用。

Serialization 是指将对象内容写到文件中,或从文件中读出。如此一来对象的生命就可以在程序结束之后还延续下去,而在程序重新启动之后,再被读入。

所谓动态的对象生成(Dynamic object creation),使你得以在运行时期产生一个特定的对象。例如document、view、和frame对象就都必须支持动态对象生成,因为framework 需要在运行时期产生它们。

此外,OLE 常常需要在运行时期做对象的动态生成动作。例如一个OLE server 程序必须能够动态产生 OLE items,用以反应 OLE client 的需求。

MFC 数据类型(data types)

下面所列的这些数据类型,常常出现在 MFC 之中。其中的绝大部分都和一般的Win32程序(SDK 程序)所用的相同。

下面这些是和 Win32 程序(SDK 程序)共同使用的数据类型:

数据类型                                  意义
BOOL                   Boolean值(布尔值,不是TRUE就是FALSE)
BSTR                   32-bit字符指针
BYTE                   8-bit整数,未带正负号
COLORREF               32-bit 数值,代表一个颜色值
DWORD                  32-bit 整数,未带正负号
LONG                   32-bit 整数,带正负号
LPARAM                 32-bit 数值,做为窗口函数或 callback 函数的一个参数
LPCSTR                 32-bit 指针,指向一个常数字符串
LPSTR                  32-bit 指针,指向一个字符串
LPCTSTR                32-bit 指针,指向一个常数字符串。此字符串可移植到Unicode和DBCS(双字节字集)
LPTSTR                 32-bit 指针,指向一个字符串。此字符串可移植到  Unicode和DBCS(双位组字集)
LPVOID                 32-bit 指针,指向一个未指定类型的数据
LPRESULT               32-bit数值,做为窗口函数或callback函数的回返值
UINT                   在Win16中是一个16-bit未带正负号整数,在Win32中是一个  32-bit未带正负号整数。
WNDPROC                32-bit 指针,指向一个窗口函数
WORD                   16-bit 整数,未带正负号
WPARAM                 窗口函数的callback函数的一个参数。在Win16中是  16 bits,在Win32中是32 bits。

下面这些是MFC独特的数据类型:

数据类型                         意义
POSITION     一个数值,代表 collection 对象(例如数组或串列)中的元素位置。常使用于MFC collection classes。
LPCRECT       32-bit指针,指向一个不变的  RECT 结构。

前面所说那些MFC数据类型与C++语言数据类型之间的对应,定义于 WINDEF.H中。我列出其中一部分,并且将不符合(_MSC_VER >= 800) 条件式的部分略去。

#define NULL 0
#define far // 侯俊杰注:Win32 不再有 far 或 near memory model,
#define near // 而是使用所谓的 flat model。pascall 函数调用习惯
#define pascal __stdcall  // 也被 stdcall 函数调用习惯取而代之。
#define cdecl _cdecl
#define CDECL _cdecl
#define CALLBACK __stdcall//侯俊杰注:在Windows programming演化过程中
#define WINAPI __stdcall  // 曾经出现的 PASCAL、CALLBACK、WINAPI、
#define WINAPIV __cdecl// APIENTRY,现在都代表相同的意义,就是 stdcall
#define APIENTRY WINAPI// 函数调用习惯。
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
#define FAR far
#define NEAR near
#define CONST const
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BOOL near *PBOOL;
typedef BOOL far *LPBOOL;
typedef BYTE near *PBYTE;
typedef BYTE far *LPBYTE;
typedef int near *PINT;
typedef int far *LPINT;
typedef WORD near *PWORD;
typedef WORD far *LPWORD;
typedef long far *LPLONG;
typedef DWORD near *PDWORD;
typedef DWORD far *LPDWORD;
typedef void far *LPVOID;
typedef CONST void far *LPCVOID;
typedef int INT;
typedef unsigned int UINT;
typedef unsigned int *PUINT;
/* Types use for passing & returning polymorphic values */
typedef UINT WPARAM;
typedef LONG LPARAM;
typedef LONG LRESULT;
typedef DWORD COLORREF;
typedef DWORD *LPCOLORREF;
typedef struct tagRECT
{
    LONG left;
    LONG top;
    LONG right;
    LONG bottom;
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;
typedef const RECT FAR* LPCRECT;
typedef struct tagPOINT
{
    LONG  x;
    LONG  y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
typedef struct tagSIZE
{
    LONG cx;
    LONG cy;
} SIZE, *PSIZE, *LPSIZE;

文章来源: https://blog.csdn.net/wang2015cn/article/details/131143575
版权声明: 本文为博主原创文章,遵循CC 4.0 BY-SA 知识共享协议,转载请附上原文出处链接和本声明。


...全文
52 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

460

社区成员

发帖
与我相关
我的任务
社区描述
微软技术社区为中国的开发者们提供一个技术干货传播平台,传递微软全球的技术和产品最新动态,分享各大技术方向的学习资源,同时也涵盖针对不同行业和场景的实践案例,希望可以全方位地帮助你获取更多知识和技能。
windowsmicrosoft 企业社区
社区管理员
  • 微软技术分享
  • 郑子铭
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

微软技术社区为中国的开发者们提供一个技术干货传播平台,传递微软全球的技术和产品最新动态,分享各大技术方向的学习资源,同时也涵盖针对不同行业和场景的实践案例,希望可以全方位地帮助你获取更多知识和技能。

予力众生,成就不凡!微软致力于用技术改变世界,助力企业实现数字化转型。

试试用AI创作助手写篇文章吧