了解如何使用
windows API
函数编程后,对
windows
应用程序的大体结构框架有初步的认识。但是直接使用
windows API
进行编程程序员需要自己编写大量代码。像我这种从一开始接触程序开发就是学习的
OO
的人来说,实在是无法忍受。从现在开始,我把重点转到
VC++
的另一方面,利用
MFC
进行和向导来编写
windows
程序。
MFC
(
Microsoft Foundation Class
)
是用来编写
windows
应用程序的
C++
类集,它封装了大量的
windows API
函数和
windows
控件,并且以层次结构组织起来。使程序员在开发时能方便的进行代码重用,加快开发速度并提高代码的可靠性。
应该注意的是
MFC
是 使用C++语言实现的一个类库,但并非是进行GUI程序设计的唯一标准。
有
OO
基础或者是学习过
JAVA
语言理解
MFC
的体系结构会比较轻松。目前,
MFC
中包含了大约
100
多个类,通过定义类对象并调用对象的成员函数来实现相应的功能。
下面简要介绍一下
MFC
的类组织结构:
1.
根类
CObject
MFC
中绝大多数类和自定义子类的根类,它提供了许多编程所需要的公共操作如:对象建立和删除、串行化支持、对象诊断、运行时信息以及集合类的兼容等
2.
命令相关类
CCmdTarget
它是
CObject
的直接子类,它是
MFC
中具有消息映射属性的基类。一般很少需要程序员直接从
CcmdTarget
直接派生新类。
3.
线程基类
CWinThread
所有线程的基类,可以直接使用,它封装了操作系统的线程化功能。
4.
窗口应用程序类
CWinApp
每个应用程序有且只有一个应用程序对象,在运行程序中该对象与其它对象相互协调,该对象从
CwinApp
类中派生而来。它封装了初始化,运行,终止应用程序的代码。
5.
文档
/
视类
CDocument/CView
文档对象由文档模板对象创建,管理应用程序的数据。
CDocument
支持标准的文档操作,这些操作包括文档创建、下载、保存等。一个应用程序可以操作多种文档类型,每一种文档类型都有特定的文档模板(
document template
)。
用户通过文档和相关联的视图对象(
CView object
)与文档进行交互。一个视图显示文档中的信息,并把用户在框架窗口内的操作转换成对文档操作的相应命令。当用户打开一个文档时,应用程序实际上创建了一个视图并把这个视图和相应的文档联系在一起。一个视图充当了沟通用户和文档对象的中间桥梁的作用。
6.
可视对象类
CWnd
该类提供了
MFC
中所有窗口类的基本功能,它的消息映射机制隐藏了窗口函数
WndProc
。一个
windows
消息通过消息映射发送到相应的
CWnd
类的
OnMessage
成员函数,通过重载
OnMessage
函数来对特定的消息进行处理。
CWnd
类有许多经常使用的子类,如
CMenu
类,
CDialog
类,
CButton
类等等。
7.
通用类
通用类提供了许多共用服务,例如文件
I/O
(
CFile
类和
CArchive
类)、异常处理(
CException
类)等。
8.
OLE
类
OLE1.0
规范是
MS
在
1991
年发布的。它是处理复合文档的一种方法:
Object Linking and Embedding
技术。所谓复合文档,就是在一个文档中同时保存了如文本、图像和声音等多种不同类型的数据,而这些数据又可以通过不同的应用程序用不同的格式产生。
1993
年发布的
OLE2.0
是基本对象的一整套体系结构,能够扩展、定制和增强服务功能,它的理论基础是
COM
技术。
此外,
ActiveX
也是一种对
OLE
技术的扩展,它使
OLE
进入
Internet
和
Intranet
。
9.
ODBC
类
为了支持带有
ODBC
驱动程序的各种数据库管理系统,
MFC
也提供了
Cdatabase
和
CRecordset
类,用于管理数据库的连接及其操作。
10.
MFC
中全局函数和变量
在
MFC
中提供的全局函数和变量一般都以
Afx
开头,它们可以在
MFC
应用程序的任务地方中使用,如:
AfxAbort
、
AfxMessageBox
等等。
在使用
VC
生成
MFC
应用程序时,
IDE
会自动生成许多代码,以一个简单的对话框程序为例,将会有如下几个主要的文件:
stdafx.h/cpp
标准系统包含文件,或是常使用但不常更改的
MFCles1.h/.cpp
应用程序类
MFCles1Dlg.h/cpp
对话框类
Resource.h
资源头文件,被
MFCles1.rc
所使用
MFC
应用程序的一般结构
就设计模式来看,
MFC
应用程序是一个标准的单例模式。每一个应用程序有且仅有一个实例对象:
theApp
程序执行的基本流程,就我现在的理解而言:
首先应该从在应用程序体系结构类中声明的一个全局实例对象
theApp
入手(C++里的全局类对象初始化在main函数之前),在进入CWinApp类的构造函数之后,程序才进入原来Windows API里的那个入口函数:AfxWinMain。
我们在写MFC程序时并没有显示的指出WinMain入口函数的位置。这个函数的定义被安置在了APPMODUL.CPP文件里(这一文件位于VS安装目录下的VC98目录里的MFC源文件里)。每个app实例被构造后,会产调用相应的InitInstance函数进行初始化。原来的注册窗口类的工作被放在了WINCORE.CPP文件里的AfxEndDeferRegisterClass函数,这里MFC已经为我们定义好了几种默认的窗口类。然后就会调用CPreCreateWnd函数进行窗口的显示工作。最后,使用CWinThread::Run方法启动消息循环,至此,整个窗口应用程序就运行起来了。windows应用程序可以被同时多次运行,第一次运行完成初始化工作后,以后每次运行程序拷贝都全调用InitInstance函数进行初始化工作。
class CMFCles1App : public CWinApp
{
public:
CMFCles1App();
//
重写一些父类方法
public:
virtual BOOL InitInstance();
//
实现消息映射的宏
DECLARE_MESSAGE_MAP()
};
extern CMFCles1App theApp;//
代码应用程序本身
以一个简单的对话框程序为例,在InitInstance函数里完成了以下工作
CMFCles1Dlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
第一行声明了一个对话框类对象,第二行将其赋值给当前应用程序类的成员变量,这是一个指向主窗口的指针,最后一行显示窗口。
了解了一点关于应用程序类的知识后,再来分析剩下的与GUI有关的另一个类,这里使用一个对话框类作一点说明。
同样,
MFCles1Dlg
则派生自
CDialog
类
class CMFCles1Dlg : public CDialog
{
public:
CMFCles1Dlg(CWnd* pParent = NULL); //
标准构造函数
protected:
HICON m_hIcon;//
应用程序图标的句柄
DECLARE_MESSAGE_MAP()
//
生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
};
DECLARE_MESSAGE_MAP()
是一个用来定义消息映射的宏,而下面以
afx_msg
开头的函数都是消息的响应函数,这比起
API
里面把消息都写在一些
switch
语句中要更清楚,也方便了修改。要实现对话框对消息的响应还需要在类中加上这两行
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
所有的消息映射函数都要写在这两行之间,例如ON_WM_RBUTTONDOWN( )就定义了一个右键按下的消息映射。MFC已经有了预定义好了许多消息映射函数的格式,需要查看可以参考MSDN。