MFC研究

来源 :硅谷 | 被引量 : 0次 | 上传用户:wo19881026
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘 要: MFC是Microsoft foundation class的简称。MFC是世界上第1个应用程序的框架类库,当时的C++还未标准化。MFC设计者们把面向对象程序设计理念引入以往过程式编程的领域,在面向对象程序设计初露头角的时候用当时还是比较低级的C++实现庞大程序框架。MFC设计庞大的类,有的类封装windows API,大大减少windows设计的工作量。MFC 6.0封装大约200个类。文中不可能对全部类的设计做讨论,而是用简单的windows程序设计中的绘图说明MFC设计的思想。最后给出MFC的处理绘图的简单例子,并给出消息映射宏的添加和MFC与STL的简要比较。
  关键词: MFC windows;API;封装;宏
  中图分类号:TP391 文献标识码:A 文章编号:1671-7597(2011)0820083-02
  
  1 MFC层次架构
  早期的windows API编程,使用的是事件驱动编程模型。程序的进入点是函数WinMain,WinMain创建窗口后进入消息循环,窗口实现的是一直等待和获取消息并处理。在MFC出现以前,主要是借助成千上万的API函数来实现窗口编程。不厌其烦的把各种设置参数填写一次又一次。
  在MFC下,函数和windows API已经作为类封装好了。并且各个类之间的关系通过纷繁复杂的宏定义紧密的联系在了一起。可以说MFC实际上是一套application framework开发工具的平台,各类之间的关系比STL复杂得多。MFC对windows开发的便利建立在一套庞大而又巧妙的类体系架构上,没有多重继承。有的是宏对各类关系之间的组织。在MFC下,Windows编程向导自动生成的类分别实现了API编程中的那些过程,封装了的windows API。可以说除了极个别的API函数,在windows API中都可以找到和MFC对应的类或者对象。MFC在编程中主要是引入了面向对象设计的思想,并且把类封装和对象概念引入了程序设计。
  类别型录网:在windows编程中,需要在不知道类名称的情况下创建类实例的能力。例如document、view、和frame对象就都必须支持动态对象生成,因为framework需要在执行时期产生它们。类的静态成员与类的实例无关,只需要将类的创建信息保存在静态成员中,调用类的静态成员就可以创建类的实例了。以静态结构CRuntimeClass描述之,这是一个结构,内中至少需有类别名称、串行的Next指针,以及串行的First指针。
  把CRuntimeClass组织成一个链表,即MFC中所有的类成员都在这张类型网中。在判断类型信息时可以到这张表中去依次搜寻。在MFC中用到了两个宏,即宏“DECLARE_DYNAMIC”对于某个特别的类声明CRuntimeClass
  信息。而把林林总总的类添加到一张类型网中则用到了“IMPLEMENT_DYNA
  MIC”宏。在完成了类型信息的登录,可以发现类似于图的一张表(实际中类数目和关系要比图复杂,此处只为便于说明类型网而简化)。
  有了类型关系网之后,对于IsKindOf(型别辨识)就实际上就是前文所说的在类型网中查找类型。MFC的基类CObject有一个IsKindOf函数(见下文代码),此函数将被所有类别继承。它将把参数所指定的某个CRuntimeClass对象拿来与类别型录中的元素一一比对。比对成功(在型录中有发现),就传回TRUE,否则传回FALSE。
  动态对象的生成Dynamic Creation把类别的大小记录在类别型录中,把构造函数也记录在类别型录中,当程序在执行时期获得一个类别名称,它就可以在类别型录网中找出对应的元素,然后调用其构造函数,产生出对象。
  2 MFC的Serialize机制
  可以这样理解,MFC实际也实现了STL的替代,并且把原STL机制实现了升级。比如说MFC的vector,queue,map等等容器,实现了Serialize机制。即把对象写入到文件。
  在MFC的底层基类CObeject有virtual void Serialize(CArchive&ar)函数和判断支持是否支持Serialize机制的布尔常量BOOL IsSerializable()const来实现特定类对Serialize机制的实现。
  Serialize机制,目的在于把文档名的选择、文件的开关、缓冲区的建立、资料的读写、萃取运算子(>>)和嵌入运算子(<<)的多载(over
  Load)、对象的动态生成等等都包装起来。在每次记录对象内容的时候,先写入一个代码,表示此对象之类别是否曾在档案中记录过了。如果是新类别,则记录其类别名称;如果是旧类别,以代码表示。这样可以节省文件大小以及程序用于解析的时间。类别之能够进行文件读写动作,前提是拥有动态生成的能力,所以,MFC设计了两个宏DECLARE_SERIAL和IMPLEMENT
  _SERIAL。对拥有动态对象生成的类实现了Serialize机制。
  3 Message Mapping(消息映射)
  Windows程序靠消息的流动而维护生命。Windows API编程中消息的一般处理方式,用一个简易的消息映射表作法,把消息和其处理例程关联起来。消息映射就是在基类中建立一张窗口消息和处理函数的对应关系存储在该表中。基类(如CWnd)为大部分窗口消息定义了处理函数,建立了二者的映射关系,这些处理函数通常对消息进行常规处理或者默认处理。而派生类的初始消息映射表是空的,如果需要,可以定义一个新的消息处理函数,并在自己的映射表中添加一项,存储该消息和该函数的对应关系。在图2的类型库中,如果其中与消息有关的类别(在MFC之中就是CCmdTarget)都是链式地继承,将基础类别与衍生类别之消息映射表串接起来。在类CCmdTarget中定义有宏DECLARE_MESSAGE_MAP(),在MFC中所有在继承自CCmdTarget都有在消息映射表中处理消息的机制。
  对MFC中消息映射机制的模拟,定义结构:
  struct AFX_MSGMAP
  {
   AFX_MSGMAP* pBaseMessageMap;父类映射表
   AFX_MSGMAP_ENTRY* lpEntries;构建消息映射表的结构数组
  };
  struct AFX_MSGMAP_ENTRY //数据结构
  {
   UINT nMessage; //消息类型
   UINT nCode; //如果是通知消息,则存储通知代码
   UINT nID; // 发送者ID(针对命令和通知消息)
   UINT nLastID; // 最后的发送者ID(针对ON_NOTIFY_RANGE 等)
   UINT nSig; // 处理函数原型的类型
   AFX_PMSG pfn; // 处理函数的指针(为CCmdTarget类的成员函数(1))
  };
  对消息映射表的查找是首先在当前派生类的消息映射表中寻找对应的处理函数,不成功就向上寻找父类映射表,直到成功或搜寻完基类为止。如果没有发现对应的处理函数,则执行形同默认的处理程序。
  4 MFC中骨干程序浅析
  在vc++.net中用向导生成的画椭圆程序中(与windows API编程下画椭圆相对应)。图3(a)为向导生成程序中VIEW类在MFC中的关系层次,CObject为所有类的基类。可以理解为显示内容的视图区。图3(b)为程序中CMainFrame类在MFC中的类关系层次,继承自CWnd.。一般可以理解为处理边框和菜单等画框部分。图3(c)为程序中CallApp类的层次结构,可以理解为windows编程的Main函数。
  在由向导生成的代码中,有前文图示的类CallApp,CChildview和CMainFrame,在MFC中程序大致的框架已经动态生成。比如要实现windows API编程所实现的椭圆,只需要在view视图中添加dc类的画图信息。最后,我们看一下,MFC中消息处理的添加。
  在CChildview中,MFC自动添加了绘图的消息映射。
  BEGIN_MESSAGE_MAP(CChildView, CWnd)
   ON_WM_PAINT()
  END_MESSAGE_MAP()
  画图只需在CChildView::OnPaint()中调用绘制设备上下文类CPaintDC中的函数就可以实现要求的效果了。
  同样的道理,在MFC中实现windows编程,主要是能熟悉所设计的类的架构,比如菜单,滚动条等需要自己改写在CMainFrame类中的代码。CMainFrame是windows框架外围的实现,需要窗口或者命令等消息时,就要像在视图CChildView中所做的那样,加入自己需要的消息。比如说文章在VS 2005中实现的程序,VS自动给出了默认的消息宏:
  BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
   ON_WM_CREATE()
   ON_WM_SETFOCUS()
  END_MESSAGE_MAP()
  其中类CMainFrame为当前类,CFrameWnd类为父类,对于消息的处理是前文所说的消息映射机制,首先在CMainFrame类中找,找不到再在父类CFrameWnd消息映射表中找。如果都找不到就调用默认的消息处理函数。
  5 MFC与STL
  MFC是一套application framework,架构比STL复杂,并且MFC中Arrays,Lists,Maps类实现了STL中容器能的功能,并且因为都继承于类CObject,MFC中的表项具有串行化功能。而在STL中需要间接实现这种功能。MFC整个架构要大得多,比如在类型表中各个类的静态信息存储和动态对象生成,以及涉及到windows编程后,消息的传递和查找等等机制。实际上MFC的设计比较宏观上比较整体。程序员添加的消息处理可能要迂回传递到基类。具体到类之间的关系,比如说CWnd类下WindowProc究竟是调用哪一个函数?不一定,得视pWnd到底派生出何种类别。如果CWnd指向CMyFrameWnd对象,那么调用的是CFrameWnd::WindowProc。而因为CFrameWnd并没有改写WindowProc,所以调用的其实是CWnd::WindowProc。
  如果CWnd 派生CMyView对象,那么调用的是CView::WindowProc。而因为CView并没有改写WindowProc,所以调用的其实是CWnd::WindowProc。虽然殊途同归,意义上是不相同的。
  
  参考文献:
  [1]本书编写组,Visual c++6.0 MFC类库参考手册[M].北京:人民邮电出版社,2002.
  [2]侯捷,深入浅出MFC[M].松崗電腦圖資料股份有限公司.
  [3]辛长安、王颜国,visual c++权威剖析[M].清华大学出版社,2008.
  [4]Jeff Prosise,MFC widows程序设计[M].北京:清华大学出版社,2008.
其他文献
丹青三甲散是著名中医耳鼻喉科专家干祖望教授治疗声音嘶哑的一首方剂.笔者在临床中以此方为基础减去鳖甲,增以蒲公英、玄参等,取名为加减丹青三甲散,治疗嗓音疾患60例,收效
据国外媒体报道,搜索引擎公司百度已经推出了一个针对Android平台的应用网店服务。该服务现在只能通过Android手机直接访问。报道称百度自身并未直接提供这些应用的下载,而仍是通过搜索的方式,提供第三方应用网店的下载地址。目前,百度Android应用目录下正在推广两个热门的应用,即带广告版本的愤怒小鸟与水果忍者。  在搜索并选择一款应用后,用户可以直接从百度页面上进行下载,无需访问第三方网站的页
摘 要: 以山东外贸职业学院下属的实验室为应用背景,在分析现有的实验室信息管理系统(LIMS)的基础上,综合运用.NET平台下的ASP.NET技术和组件技术,实现一个人性化的、适合高等院校实验室管理者和应用者使用的实验室信息管理系统。本系统为高校实验的管理者和应用者提供很大的便利,不仅能让管理者方便地管理实验室的相关信息,规范实验室的管理流程,提高实验室的利用率,还能让应用者(教师和学生)及时了
本文通过对荣华二采区10
期刊
摘 要: 简单介绍UPS电源的工作原理,主要介绍UPS电源所采用的六种先进技术和提高UPS可靠性的三种方法。  关键词: UPS电源;绝缘栅双极型晶体管;可靠性  中图分类号:TM910 文献标识码:A 文章编号:1671-7597(2011)0820082-01    1 UPS电源工作原理  UPS电源按输出波形可分为方波输出和正弦波输出两大类。按其操作方式可分为后备式和在线式。其中后备