`
jhs470ai
  • 浏览: 13198 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

MFC类库的产生与发展

阅读更多

MFC类库的产生与发展
2011年07月01日
  在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版本 MFC中的类按照功能的不同,可以分为不同的层次。图1.10显示了MFC中的所有类及类库层次。 MFC中的数据类型与Windows SDK开发包中的数据类型多数是一致的,但也有一些数据类型是MFC独有的。表1.5列出了MFC中使用的数据类型。
  表1.5中列出的最后两个数据类型是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 异常抛出函数 续表 函数名称 描述 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.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函数。用户可以按键进入到_tWinMain函数,如图1.17所示。 
  
  图1.17 _tWinMain函数 _tWinMain函数与WinMain函数有什么关系呢?将光标定位在"_tWinMain"处,按键查看其定义,发现_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方法在内部调用一系列的函数,实现窗口类的注册、创建窗口、进入消息循环等功能。有关模态对话框的相关知识在后面章节会详细介绍。
分享到:
评论

相关推荐

    MFC实战参考程序

    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 ...

    MFC Windows程序设计(第2版修订版)--源代码

    一部分是由于VisualC++代码生成向导所生成的代码所致,另一个原因是因为无数行代码隐藏在MFC类库中。这正是本书使用特殊的方法来写MFC的缘由。本书从让您亲自手写代码开始(不用向导),使用MFCl.0的应用程序结构风格...

    MFC Windows程序设计(第2版修订版)--详细书签版2卷

    一部分是由于VisualC++代码生成向导所生成的代码所致,另一个原因是因为无数行代码隐藏在MFC类库中。这正是本书使用特殊的方法来写MFC的缘由。本书从让您亲自手写代码开始(不用向导),使用MFCl.0的应用程序结构风格...

    MFC Windows程序设计(第2版修订版)--详细书签版1卷

    一部分是由于VisualC++代码生成向导所生成的代码所致,另一个原因是因为无数行代码隐藏在MFC类库中。这正是本书使用特殊的方法来写MFC的缘由。本书从让您亲自手写代码开始(不用向导),使用MFCl.0的应用程序结构风格...

    C#微软培训资料

    2.2 公用语言运行时环境与公用语言规范.13 2.3 开 发 工 具 .17 2.4 小 结 .19 第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 ...

    C++标准库介绍.pdf

     跨平台GUI库其类层次极像MFC所以有文章介绍从MFC到WxWindows代码移植以实现跨平台功能通过多 年开发也是个日趋完善GUI库支持同样不弱于前面两个库并且是完全开放源代码新近C Builder XGUI设计器就 是基于这个库 4...

Global site tag (gtag.js) - Google Analytics