微软MFC技术运行机制

我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下微软MFC技术运行机制。

很多初学者误以为VC++开发必须使用MFC,其实不一定的。MFC的使用只能是提高程序在某些情况下的开发效率,而不能替代整个Win32程序设计。我认为我们有必要再来好好讲讲MFC的本质、MFC中的消息是以何种形式存在、懂得MFC中消息的存储方式消息队列、明白MFC程序运行的原理消息响应、MFC运行流程。

我在上一篇关于MFC的文章中说过,MFC是微软公司提供的类库,它以C++的形式封装了Windows的接口函数API。类库中包含大量的Windows句柄类、Windows控件类、Windows组件类。

直接使用Windows的API函数来开发产品,对于程序员来说很困难。因为API函数的数量十分多,而且名称上有时很难看出来是什么意思。如果用win32开发一个窗口至少也得100多行的代码,而一个软件系统做出来后,那代码量更是大的惊人。本质上来说,MFC就是win32开发与Application framework的组合。这个组合为程序员创建了程序的一般框架模型,减少了应用程序开发程序员的工作量。

为了方便大家理解MFC,现在我们做一个比喻。我们把MFC程序比喻为空调。

首先,威利斯·开利发明了世界上第一台空调,是下图这个样子的,于是空调的整个设计思想和原理被固定下来,形成了第一代空调,相当于我们这里的Win32的Application framework。

而最新的空调就是在第一代空调的基础上不断迭代发展而来。现代空调是在第一代空调的基础上不断完善而来,增加入不少新的技术,这种增加的新技术类似于我们这里的各类Windows的接口函数API,然后对第一代空调的设计思想原理结合后来的新技术进行了一次次的融合,而且更加模块化组件化,形成了现代空调产品,也就是我们这里的MFC。如下图这些工业用空调。

MFC的实质就是对Win32程序的封装,第一台空调与后来各种技术的结合 就是现代空调发展的一个模板,Win32的Application framework与函数API的结合 就是MFC框架。

你如果想在现代空调上加入新技术,就必须了解空调的原理。对于程序员来说,也必须了解MFC架构。MFC程序的结构一般是由一个CWinApp类对象和几个从MFC派生的类组成。

我们以一个基于单文档的MFC工程为例进行讲解,工程名为KongTiao。我们一建立KongTiao就会有如下图几个类,其中常用的是CMainFrame、CKongTiaoApp、CKongTiaoDoc、CKongTiaoView这4个类。

1.应用程序类CKongTiaoApp
先在KongTiao.h通过下面代码定议CKongTiaoApp类。

class CKongTiaoApp : public CWinApp //派生类:public 基类
{
 public:
       CKongTiaoApp(); //构造函数,用于初始化
 public:
       virtual BOOL InitInstance(); //实例化虚函数
       afx_msg void OnAppAbout(); //函数声明
       DECLARE MESSAGE_MAP()

从第01行可看出它是从CWinApp类派生,它有且只有一个应用程序对象,负责应用程序的初始化、运行和结束。

2.文档类CKongTiaoDoc
先在KongTiaoDoc.h通过下面代码定义CKongTiaoDoc类。

class CKongTiaoDoc : public CDocument  //派生类:public基类
  {  
  protected:        //以下为保护成员函数
      CKongTiaoDoc();    //构造函数,用于初始化
      DECLARE DYNCREATE(CMessageDoc)
  ...
  public:
  virtual ~CKongTiaoDoc();    //析构函数
  ...
  };

从它的第01行可看出它是从CDocument类派生,用来管理数据,实现数据的变化、存取。

3.视图类CMessageView
同时文档类还可以和视图类合作,访问和更新数据。先在KongTiaoView.h通过下面代码进行定义,也就是CKongTiaoView视图类的定义。

class CKongTiaoview : public CView    //派生类:public基类
{
  protected:      //以下为保护成员函数
      CKongTiaoView();  //构造函数,用于初始化
      DECLARE DYNCREATE(CKongTiaoview)
  ...
  public:
      virtual void OnDraw(CDC* pDC);  //画视图
      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  //创建窗口
  ...
  public:
      virtual ~CKongTiaoView();  //析构函数
  ...
  protected:
      DECLARE MESSAGE MAP()
  public:
      afx msg void OnMouseMove(UINT nFlags, CPoint point);  //鼠标移动的消息函数
};

从第01行可看出它是从CView类派生。视图和文档联系在一起,在文档和用户之间起中介作用,即:在屏幕上显示文档的内容,并把用户输入转换成对文档的操作。

4.主框架窗口类CMainFrame

代码MainFrm.h是CMainFrame框类的定义。
 

class CMainFrame : public CFrameWnd      //派生类:public基类
{
  protected:    //以下为保护成员函数
      CMainFrame();    //构造函数,用于初始化
      DECLARE DYNCREATE(CMainFrame)
  ...
  public:
      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);   //创建窗口
  public:
      virtual ~CMainFrame();    //析构函数
  ...
  protected:
      CStatusBar m_wndStatusBar;     //声明一个状态栏对象
       CToolBar m_wndToolBar;     //声明一个工具栏对象
  protected:
      afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);    //用于创建窗口各种属性
      DECLARE_MESSAGE MAP()
  };

从第01行可看出它是从CFrameWnd类派生,负责创建和控制菜单、工具栏、状态栏等界面元素。

5.MFC类的底部派生关系

前面大家已经看到很多类的派生关系,这4个默认生成的类都是从CWinApp、CDocument 等类派生而来,这就需要大家了解MFC类的底部派生关系,如图所示。


第 1行的 CObject 类是大多数 MFC 类的根类或基类。 CObject派生出CCmdTarget。类 CCmdTarget 是MFC类库中消息映射体系的一个基类,是MFC处理命令消息的基础核心。而CCmdTarget类又派生出了如图中所示4种不同的类,即CWinThread、CDocTemplate、 CDocument、CWnd。

CWinThread:是MFC用来封装线程的。每个MFC程序至少使用一个 CWinThread派生类。而MFC程序员熟知的CWinApp应用类就是从此处派生,这个派生关系可以从图直观看出。

CDocTemplate:是抽象的基类,它定义了文档模板的基本函数功能。但它不能直接使用,通常应用的是由其派生的两个类。一个是CSingleDocTemplate,其用于SDI;另一个是MultiDocTemplate,其用于MDI。

CDocument:它为用户定义的文档类提供了基本的函数功能。

CWnd:是 MFC 窗口类的基类,提供了微软基础类库中所有窗口类的基本功能,它是MFC学习的重中之重。由它派生出了3个类:CFrameWnd、CView、CControlBar。其中前两个类就是读者的学习重点。

注意:CDocTemplate类对于大家来说,可以暂且不去关注它。在大家的学习范围中,很少涉及到此类。

提到MFC,不能不说应用程序框架,提到框架,又不能不说视图和文档。下面再详细介绍下这两个类:CFrameWnd(负责主窗口)和CView(负责视图)。

CFrameWnd:往往用于创建应用程序的主窗口,它能很好地支持系统菜单和控制条。CFrameWnd直接支持单文档界面(SDI),对于多文档界面(MDI),则使用其派生类CMDIFrameWnd和CMDIChildWnd。

CView:是MFC程序设计中使用率最高的窗口对象,它是用户的主要操作界面。因为它通常以某种形式表示文档数据,所以称之为视图。一个视图对象只关联一个文档对象,而一个文档对象可以关联多个视图,每个视图对象以不同形式表示文档数据。

为了更直观地了解MFC程序的文件构成,新建一个MFC单文档工程,命名为Message。此工程一经建立就会自动生成许多头文件和源文件,如图所示。

 自动生成的这些文件的名字及对应文件的用途通过两个表格来说明。如下表是AppWizard所生成的头文件。

下表是AppWizard所生成的源文件。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值