MFC类库的产生与发展
在Microsoft推出Windows
3.0之后,Windows操作系统受到越来越多的人的青睐。但是不久,开发人员发现撰写Windows应用程序是重复、厌烦的过程,而且效率极低。因为每一个窗口都需要在窗口函数中处理大量的消息,导致出现大量的重复代码。
随着C++语言的盛行,开发人员发现利用C++语言的特性来封装Windows
API和Windows应用程序的开发可以明显地提高程序的开发效率。于是,人们对这种新的开发模式有了强烈的需求。在这种情况下,Microsoft公司和其他一些大的厂商开始从事Windows框架的设计。MFC就在这种背景下诞生了。
MFC的英文全称是Microsoft Fundation Class
Library,即微软基础类库。从其产生至今已经发展了十几个版本,表1.4列出的是MFC的发展过程。
表1.4
MFC发展过程
MFC
|
Visual C++
|
MFC 1.0版本
|
Microsoft C/C++ 7.0版本
|
MFC 2.0版本
|
Visual C++ 1.0版本
|
MFC 2.5版本
|
Visual C++ 1.5版本
|
MFC 3.0版本
|
Visual C++ 2.0版本
|
MFC 3.1版本
|
Visual C++ 2.1版本
|
MFC 3.2版本
|
Visual C++ 2.2版本
|
MFC 4.0版本
|
Visual C++ 4.0版本
|
MFC 4.1版本
|
Visual C++ 4.1版本
|
MFC 4.2版本
|
Visual C++ 4.2版本
|
MFC 4.21版本
|
Visual C++ 5.0版本
|
MFC 6.0版本
|
Visual C++ 6.0版本
|
MFC 7.0版本
|
Visual C++.NET 2002版本
|
MFC 7.1版本
|
Visual C++.NET 2003版本
|
MFC 8.0版本
|
Visual C++.NET 2005版本
|
1.5.2 MFC类库层次
MFC中的类按照功能的不同,可以分为不同的层次。图1.10显示了MFC中的所有类及类库层次。
1.5.3 MFC常用数据类型
MFC中的数据类型与Windows
SDK开发包中的数据类型多数是一致的,但也有一些数据类型是MFC独有的。表1.5列出了MFC中使用的数据类型。
表1.5中列出的最后两个数据类型是MFC所特有的。
1.5.4 MFC全局函数
在MFC类库中,除了提供实现各种功能的类以外,还提供许多全局函数。具体介绍如下。
表1.5
MFC数据类型
数 据 类 型
|
描 述
|
BOOL
|
布尔值,取值为TRUE或FALSE
|
BSTR
|
32位字符指针
|
BYTE
|
8位无符号整数
|
COLORREF
|
用作颜色值的32位数值
|
DWORD
|
32位无符号整数,或者段的地址和与之相关的偏移量
|
LONG
|
32位有符号整数
|
LPARAM
|
32位值,作为窗口函数或回调函数的参数
|
LPCSTR
|
指向字符串常量的32位指针
|
LPSTR
|
32位字符串指针
|
LPCTSTR
|
指向兼容Unicode和DBCS字符集的字符串常量32位指针
|
LPTSTR
|
指向兼容Unicode和DBCS字符集的字符串32位指针
|
LPVOID
|
指向一个未定义类型的32位指针
|
LRESULT
|
窗口函数或回调函数返回的32位值
|
UINT
|
32位无符号整数
|
WNDPROC
|
指向一个窗口函数的32位指针
|
WORD
|
16位无符号整数
|
WPARAM
|
作为参数传递给窗口函数或回调函数的值
|
POSITION
|
用于标记集合中一个元素的位置
|
LPCRECT
|
指向一个RECT结构体常量的32位指针
|
1.MFC诊断函数
为了调试的方便,MFC提供了多个诊断函数,如表1.6所示。
表1.6
MFC诊断函数
函 数 名 称
|
描 述
|
AfxCheckMemory
|
检查当前分配的所有内存的完整性
|
AfxDump
|
如果在调试器内调用,则转存对象的状态
|
AfxDumpStack
|
生成当前栈的一个映像,该函数通常被静态链接
|
AfxEnableMemoryTracking
|
打开或关闭内存跟踪
|
AfxIsMemoryBlock
|
检验一个内存块是否被正确地分配
|
AfxIsValidString
|
检验一个字符串指针是否有效
|
AfxSetAllocHook
|
允许在每次进行内存分配时调用一个函数
|
AfxDoForAllClasses
|
对所有从CObject继承的支持运行时检查的类执行一个特定的功能
|
AfxDoForAllObjects
|
对所有从CObject继承的用new分配内存的对象执行一个指定的功能
|
2.异常抛出函数
为了使程序具有健壮性,MFC提供了多个异常抛出函数,如表1.7所示。
表1.7
异常抛出函数
函 数 名 称
|
描 述
|
AfxThrowArchiveException
|
抛出一个档案异常
|
AfxThrowFileException
|
抛出一个文件异常
|
续表
函 数 名 称
|
描 述
|
AfxThrowMemoryException
|
抛出一个内存异常
|
AfxThrowNotSupportedException
|
抛出一个不支持的异常
|
AfxThrowResourceException
|
抛出一个Windows未找到资源的异常
|
AfxThrowUserException
|
在用户初始化的程序动作中抛出一个异常
|
AfxThrowOleException
|
抛出一个OLE异常
|
AfxThrowOleDispatchException
|
在OLE自动化函数内抛出异常
|
AfxThrowDaoException
|
从代码中抛出一个CDaoException异常
|
AfxThrowDBException
|
从代码中抛出一个CDBException异常
|
3.字符串格式和消息框函数
MFC除了提供CString类操作字符串外,还提供了两个全局函数,如表1.8所示。
表1.8 字符串格式和消息框函数
函 数 名 称
|
描 述
|
AfxFormatString1
|
用一个字符串替换给定字符串中的格式字符“%1”
|
AfxFormatString2
|
用两个字符串替换给定字符串中两个格式字符“%1”和“%2”
|
AfxMessageBox
|
显示一个消息框
|
4.应用程序信息和管理函数
MFC提供的与应用程序有关的全局函数如表1.9所示。其中,有许多函数在开发应用程序过程中经常使用。
表1.9 应用程序信息和管理函数
函 数 名 称
|
描 述
|
AfxFreeLibrary
|
减少已调入内存的动态链接库模块的引用计数;当引用计数减到0时,该模块就会被释放
|
AfxGetApp
|
返回应用程序对象CWinApp的一个指针
|
AfxGetAppName
|
返回应用程序的名称
|
AfxGetInstanceHandle
|
返回应用程序实例句柄
|
AfxGetMainWnd
|
返回指向非OLE应用程序的当前主窗口指针,或者是服务器程序的线程框架窗口
|
AfxGetResourceHandle
|
返回应用程序默认的资源
|
AfxInitRichEdit
|
为应用程序初始化RichEdit控件
|
AfxLoadLibrary
|
调入一个DLL模块,同时返回一个句柄,通过该句柄可以获得DLL中函数的地址
|
AfxRegisterWndClass
|
注册一个Windows窗口类,用它来代替MFC自动注册的窗口类
|
AfxSocketInit
|
在应用程序的InitInstance方法中调用,用于初始化套接字
|
AfxSetResourceHandle
|
设置应用程序默认的资源句柄
|
AfxRegisterClass
|
在使用MFC的DLL中注册窗口类
|
AfxBeginThread
|
创建一个新的线程
|
AfxEndThread
|
结束一个线程
|
AfxGetThread
|
获取指向当前CWinThread对象的指针
|
AfxWinInit
|
由MFC提供的WinMain函数直接调用,在GUI应用程序中,用于初始化MFC
|
5.集合类帮助函数
集合类帮助函数多用于数组操作。表1.10列出了MFC提供的集合类帮助函数。
表1.10
集合类帮助函数
函 数 名 称
|
描 述
|
CompareElements
|
比较元素是否相同
|
ConstructElements
|
当生成一个元素时必须实现的动作
|
CopyElements
|
将元素从一个数组中复制到另一个数组中
|
DestructElements
|
当销毁一个数组时需要实现的动作
|
DumpElements
|
提供了面向流的诊断输出
|
HashKey
|
计算一个Hash键
|
SerializeElements
|
将元素保存到文件中,或从文件中获得元素
|
6.记录字段交换函数
记录字段交换函数用于记录集数据与变量的交互。表1.11列出了与记录字段相关的函数。
表1.11
记录字段交换函数
函 数 名 称
|
描 述
|
RFX_Binary
|
传送CByteArray类型的字节数
|
RFX_Bool
|
传送布尔数据
|
RFX_Byte
|
传送单个字节数据
|
RFX_Date
|
传送CTime或TIMESTAMP_STRUCT类型的时间和日期数据
|
RFX_Double
|
传送双精度浮点数据
|
RFX_Int
|
传送整型数据
|
RFX_Long
|
传送长整型数据
|
RFX_LongBinary
|
通过CLongBinary类的对象传送二进制大对象
|
RFX_Single
|
传送浮点数据
|
RFX_Text
|
传送字符串数据
|
RFX_Binary_Bulk
|
传送二进制数据的数组
|
RFX_Bool_Bulk
|
传送布尔数据的数组
|
RFX_Date_Bulk
|
传送TIMESTAMP_STRUCT数据的数组
|
RFX_Double_Bulk
|
传送双精度浮点数据数组
|
RFX_Int_Bulk
|
传送整型数据数组
|
RFX_Long_Bulk
|
传送长整型数据数组
|
RFX_Single_Bulk
|
传送浮点数据数组
|
RFX_Text_Bulk
|
传送LPSTR数据数组
|
7.OLE相关函数
为了支持OLE技术,MFC对OLE进行了封装,同时提供了一些全局函数用于OLE操作,如表1.12所示。
表1.12
OLE相关函数
函 数 名 称
|
描 述
|
AfxOleInit
|
初始化OLE库
|
AfxOleCanExitApp
|
判断应用程序是否能够结束
|
AfxOleGetMessageFilter
|
获取应用程序当前的消息过滤器
|
AfxOleGetUserCtrl
|
获取当前的用户控制标记
|
续表
函 数 名 称
|
描 述
|
AfxOleSetUserCtrl
|
设置或清除用户控制标记
|
AfxOleLockApp
|
增加应用程序中活动对象的全局计数
|
AfxOleUnlockApp
|
减少应用程序中活动对象的全局计数
|
AfxOleRegisterServerClass
|
在OLE系统注册表中注册一个服务器
|
AfxOleSetEditMenu
|
实现TypeName Object命令的用户接口
|
AfxOleRegisterControlClass
|
在注册数据库中添加控件类
|
AfxOleRegisterPropertyPageClass
|
在注册数据库中添加控件的属性页类
|
AfxOleRegisterTypeLib
|
在注册数据库中添加控件的类型库
|
AfxOleUnregisterClass
|
从注册数据库中删除控件类或属性页类
|
AfxOleUnregisterTypeLib
|
从注册数据库中删除控件的类型库
|
8.Internet URL解析全局函数
为了获得URL字符串的相关信息,MFC提供了两个全局函数,如表1.13所示。
表1.13 Internet
URL解析全局函数
函 数 名 称
|
描 述
|
AfxParseURL
|
分析一个URL字符串,返回服务器的类型及内容
|
AfxParseURLEx
|
分析一个URL字符串,返回服务器的类型及内容,同时返回系统用户的名字和密码
|
1.5.5 开发基于MFC的应用程序
在1.4.5节中介绍了利用Windows
API开发Win32应用程序。本节将介绍如何开发基于MFC的应用程序。
实例位置:光盘/mingrisoft/sl/01/02/MFCApp.dsw
具体步骤如下。
(1)单击“File/New”菜单项,打开“New”对话框,选择“Projects”选项卡,如图1.11所示。
图1.11 MFC应用程序
(2)在列表中选择“MFC
AppWizard(exe)”选项,在“Project name”编辑框中输入工程名称,此时“OK”按钮变为可用,单击该按钮进入“MFC
AppWizard-Step1”对话框,如图1.12所示。
图1.12 “MFC AppWizard-Step1”对话框
(3)在“MFC
AppWizard-Step1”对话框中选择应用程序的类型。这里共有3种类型可供选择,分别为“Single
document(单文档应用程序)”、“Multiple documents(多文档应用程序)”和“Dialog
based(对话框应用程序)”。这里选择“Dialog based”,即创建基于对话框的应用程序。
(4)单击“Next”按钮,进入“MFC AppWizard-Step
2 of 4”对话框,如图1.13所示。
图1.13 “MFC AppWizard-Step 2 of
4”对话框
(5)保留默认的设置,单击“Next”按钮,进入“MFC
AppWizard-Step 3 of 4”对话框,如图1.14所示。
(6)单击“Next”按钮,进入“MFC AppWizard-Step
4 of 4”对话框,在该对话框中列出了MFC向导创建的类,如图1.15所示。
图1.14 “MFC AppWizard-Step 3 of 4”对话框
图1.15 “MFC AppWizard-Step 4 of 4”对话框
(7)单击“Finish”按钮,完成工程的创建。运行程序,效果如图1.16所示。
图1.16 MFC应用程序
使用MFC应用程序向导,没有编写一句代码,就创建出了一个对话框。与1.4.5节中的程序开发过程相比,简单了许多,这就是MFC的优势。
但是,读者似乎会产生疑问,在上面的工程中并没有发现程序的入点函数WinMain。下面将剖析程序的执行过程,读者在其中会找到答案。
在编译应用程序的时候,首先会构造工程中的全局对象,即先创建全局对象。在上面创建的工程中,读者可以找到MFC应用程序向导创建的全局对象theApp。因此会执行theApp类的构造函数,接着链接器加载代码,执行_tWinMain函数。用户可以按<F11>键进入到_tWinMain函数,如图1.17所示。
图1.17 _tWinMain函数
_tWinMain函数与WinMain函数有什么关系呢?将光标定位在“_tWinMain”处,按<F12>键查看其定义,发现_tWinMain其实是一个宏,等价于WinMain函数,如图1.18所示。
图1.18 _tWinMain宏定义
在_tWinMain函数中,调用了AfxWinMain函数,而AfxWinMain函数又调用了AfxWinInit函数,然后又调用了应用程序的InitApplication方法、InitInstance方法,如图1.19所示。
图1.19 AfxWinMain函数
在图1.19中注意“pThread->InitInstance()”语句,其中pThread是一个CWinThread对象指针,通过调用AfxGetThread函数获得。上文中笔者说在AfxWinMain函数中调用了应用程序的InitInstance方法,应用程序与pThread有何关系呢?其实应用程序CWinApp的父类就是CWinThread。在CWinThread类中定义了虚拟方法InitInstance,依据动态绑定的原则,“pThread->InitInstance()”语句实际上调用的是应用程序的InitInstance方法。本例中InitInstance方法代码是由MFC应用程序向导自动生成的,代码如下:
BOOL CMFCAppApp::InitInstance()
{
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls();
#else
Enable3dControlsStatic();
#endif
CMFCAppDlg dlg; //定义一个对话框对象
m_pMainWnd = &dlg; //将对话框设置为应用程序的主窗口
int nResponse = dlg.DoModal(); //创建一个模态对话框
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}
return FALSE;
}
在应用程序的InitInstance方法中,对话框dlg调用了DoModal方法,该方法用于创建一个模态对话框。DoModal方法在内部调用一系列的函数,实现窗口类的注册、创建窗口、进入消息循环等功能。有关模态对话框的相关知识在后面章节会详细介绍。
分享到:
相关推荐
1.5.1 MFC类库的产生与发展 15 1.5.2 MFC类库层次 15 1.5.3 MFC常用数据类型 15 1.5.4 MFC全局函数 15 1.5.5 开发基于MFC的应用程序 20 1.6 Visual C++ 6.0集成开发环境 24 1.6.1 开发环境 24 1.6.2 ...
一部分是由于VisualC++代码生成向导所生成的代码所致,另一个原因是因为无数行代码隐藏在MFC类库中。这正是本书使用特殊的方法来写MFC的缘由。本书从让您亲自手写代码开始(不用向导),使用MFCl.0的应用程序结构风格...
一部分是由于VisualC++代码生成向导所生成的代码所致,另一个原因是因为无数行代码隐藏在MFC类库中。这正是本书使用特殊的方法来写MFC的缘由。本书从让您亲自手写代码开始(不用向导),使用MFCl.0的应用程序结构风格...
一部分是由于VisualC++代码生成向导所生成的代码所致,另一个原因是因为无数行代码隐藏在MFC类库中。这正是本书使用特殊的方法来写MFC的缘由。本书从让您亲自手写代码开始(不用向导),使用MFCl.0的应用程序结构风格...
2.2 公用语言运行时环境与公用语言规范.13 2.3 开 发 工 具 .17 2.4 小 结 .19 第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 ...
跨平台GUI库其类层次极像MFC所以有文章介绍从MFC到WxWindows代码移植以实现跨平台功能通过多 年开发也是个日趋完善GUI库支持同样不弱于前面两个库并且是完全开放源代码新近C Builder XGUI设计器就 是基于这个库 4...