您的位置:首页 > 编程语言 > C语言/C++

VC++60 第十六章 VC++开发工具和MFC基础类库(四)

2016-10-13 18:50 295 查看
VC++60 第十六章 VC++开发工具和MFC基础类库(四)

 

16.4 MFC基础类库

Microsoft提供了一个基础类库MFC,其中包含用来开发C++和C++ Windows应用程序的一组类。基础类库的核心是以C++形式封装了大部分的Windows API。类库表示窗口、对话框、设备上下文、公共GDI对象如画笔、调色板、控制框和其他标准的Windows部件。这些类提供了一个面向Windows中结构的简单的C++成员函数的接口。

1 基础类,宏和全程函数

MFC可分为两个主要部分:基础类,宏和全程函数。

1) MFC的基础类

MFC的基础类按功能来分可划分为以下几类:基类、应用程序框架类、应用程序类、命令相关类、文档/视类、线程类、可视对象类、窗口类、视类、对话框类、属性表、控制类、菜单、设备描述表、绘画对象类、通用类、文件、诊断、异常、收集、模板收集、其他支持类、OLE2类、OLE基类、OLE可视编辑包装程序类、OLE可视编辑服务器程序类、OLE数据传输类、OLE对话框类、其他OLE类、数据库类。

宏和全局函数

    若某个函数或变量不是某个类的一个成员,那么它是一个全程函数或变量。Microsoft基本宏和全程函数提供以下功能:

数据类型

运行时刻对象类型服务

诊断服务

异常处理

CString格式化及信息框显示

消息映射

应用消息和管理

对象连接和嵌入(OLE)服务

标准命令和Windows IDs

    

约定:全程函数以“Afx”为前缀,所有全程变量都是以“afx”为前缀,宏不带任何特别前缀,但是全部大写。常见的全局函数和宏有:AfxGetApp,AfxGetMainWnd,AfxMessageBox,DEBUG_NEW等。
2) MFC的消息机制

Windows消息的管理包括消息发送和处理。为了支持消息发送机制,MFC提供了三个函数:SendMessage、PostMessage和SendDlgItemMessage。而消息处理则相对来说显得复杂一些。MFC采用了一种新的机制取代C语言编程时对Windows消息的Switch/Case分支,简化了Windows编程,使程序可读性、可维护性大大提高。

MFC对消息的处理

   MFC采用一种消息映射机制来决定如何处理特定的消息,这种消息映射机制包括一组宏,用于标识消息处理函数、映射类成员函数和对应的消息等。其中,用afx_msg放在函数返回类型前面,用以标记它是一个消息处理成员函数。类若至少包含了一个消息处理函数,那么还需要加上一个DECLARE_MESSAGE_MAP()宏,该宏对程序执行部分所定义的消息映射进行初始化。例如:

//{{AFX_MSG(CMainFrame)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

    afx_msg void OnEditCopy();

    afx_msg void OnClose();
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()

成员函数OnCreate,OnEditCopy,OnClose分别用来处理消息WM_CREATE、ID_EDIT_COPY和WM_CLOSE。其中,WM_CREATE和WM_CLOSE是系统预定义消息,包含在Windows.h中。而ID_EDIT_COPY是菜
4000
单Edit->Copy的标识,也就是用户选择Edit->Copy菜单项时产生的消息,一般在资源文件头文件中定义。在类的实现部分给出这三个成员函数的定义,以及特殊的消息映射宏。上面的例子的消息映射宏定义如下:

BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)

    ON_WM_CREATE()

    ON_COMMAND(ID_EDIT_COPY, OnEditCopy)

    ON_WM_CLOSE()

END_MESSAGE_MAP()

消息映射宏由BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()。其中,BEGIN_MESSAGE_MAP宏包含两个参数CMainFrame类和CFrameWnd,分别代表当前定义的类和它的父类。在BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()之间,包含了主窗口要处理的各个Windows消息的入口。在本例中,包含三个消息。其中ON_
WM_CREATE被用来指定缺省的成员函数OnCreate与WM_CREATE相对应。在MFC中,包含了大量的预定义消息映射宏,用来指定各种成员函数与各种形如WM_XXXX消息相对应。如ON_WM_CLOSE宏指定了WM_CLOSE消息的处理成员函数为OnClose。这时侯,只需要写出要处理的消息就够了,不必再写出处理函数。消息映射宏ON_COMMAND则被用来将菜单项和用户自定义的命令同它们的处理成员函数联系起来。在上例中,用户选择Edit->Copy菜单项时,系统执行OnEditCopy()函数。ON_COMMAND宏的一般定义形式如下:

ON_COMMAND(command,command_function)

    其中,command为菜单消息或用户自定义消息,command_function为消息处理函数。

 

3 更新命令用户接口消息UPDATE_COMMAND_UI

在ClassWizard的Message Map页中,如果我们选择一个菜单ID,在Messages列表框中就会出现两项:

    COMMAND 和 UPDATE_COMMAND_UI,

其中UPDATE_COMMAND_UI就是更新命令用户接口消息,专门用于处理菜单项和工具条按钮的更新。每一个菜单命令都对应于一个更新命令用户接口消息。可以为更新命令用户接口消息编写消息处理函数来处理用户接口(包括菜单和工具条按钮)的更新。如果一条命令有多个用户接口对象(比如一个菜单项和一个工具条按钮),两者都被发送给同一个处理函数。这样,对于所有等价的用户接口对象来说,可以把用户接口更新代码封装在同一地方。

用户接口更新原理

  为了理解用户接口更新机制,我们来看一下应用框架是如何实现用户接口更新的。当我们选择Edit菜单时,将产生一条WM_INITMENUPOPUP消息。框架的更新机制将在菜单拉下之前集体更新所有的项,然后再显示该菜单。

  为了更新所有的菜单项,应用框架按标准的命令发送路线把该弹出式菜单中的所有菜单项的更新命令都发送出去。通过匹配命令和适当的消息映射条目(形式为ON_UPDATE_COMMAND_UI),并调用相应的更新处理器函数,就可以更新任何菜单项。比如,Edit菜单下有Undo、Cut、Copy、Paste等四个菜单项,就要发送四条用户接口更新命令。如果菜单项的命令ID有一个更新处理器,它就会被调用进行更新;如果不存在,则框架检查该命令ID的处理函数是否存在,并根据需要使菜单有效或无效。

  如果在命令发送期间找不到对应于该命令的ON_UPDATE_COMMAND_UI项,那么框架就检查是否存在一个命令的ON_COMMAND项,如果存在,则使该菜单有效,否则就使该菜单无效(灰化)。这种更新机制仅适用于弹出式菜单,对于顶层菜单象File和Edit菜单,就不能使用这种更新机制。

  按钮的命令更新机制与菜单的命令接口更新机制类似,只是工具条按钮的命令接口更新在空闲循环时完成。

 

4 学习MFC的方法

首先要对Windows API有一定的了解,否则无法深入学习MFC。至少要知道Windows对程序员来说意味着什么,它能完成什么工作,它的一些常用数据结构等。

另一点是不要过分依赖于Wizards。Wizards能做许多工作,但同时掩饰了太多的细节。应当看看AppWizard和ClassWizard为你所做的工作。在mainfrm.cpp中运行调试器来观察一下MFC运行的流程。除非你理解了生成的代码的含义,否则无法了解程序是如何运行的。

还有很重要的一点就是要学会抽象的把握问题,不求甚解。许多人一开始学习Visual C++就试图了解整个MFC类库,实际上那几乎是不可能的。一般的学习方法是,先大体上对MFC有个了解,知道它的概念、组成、基本约定等。从最简单的类入手,由浅入深,循序渐进、日积月累的学习。一开始使用MFC提供的类时,只需要知道它的一些常用的方法、外部接口,不必要去了解它的细节和内部实现,把它当做一个模块或者说黑盒子来用,这就是一种抽象的学习方法。在学到一定程度时,再可以深入研究,采用继承的方法对原有的类的行为进行修改和扩充,派生出自己所需的类。

学习MFC,最重要的一点是理解和使用MFC类库,而不是记忆。

——全书完  东方一峰于2009年4月—— 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: