3 MFC应用程序框架
MFC应用程序框架可以看作是MFC基本类库的一个超集(Superset),类库是众多可在任何程序中使用的类的集合,而应用程序框架则定义了程序自身的结构。下面给出一个使用了MFC应用程序框架的简单例子,通过这段例程可以比较清楚地了解MFC应用程序框架的一般结构。
// Sample01.h文件 // 应用程序类 class CSample01App : public CWinApp { public: virtual BOOL InitInstance(); }; // 框架窗口类 class CSample01Frame : public CFrameWnd { public: CSample01Frame(); protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; // Sample01.cpp文件 #include <afxwin.h> #include "Sample01.h" // 应用程序对象 CSample01App theApp; // 初始化应用程序实例 BOOL CSample01App::InitInstance() { m_pMainWnd = new CSample01Frame(); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } // 消息映射 BEGIN_MESSAGE_MAP(CSample01Frame, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() // 构造函数 CSample01Frame::CSample01Frame() { Create(NULL, "MFC应用程序框架程序"); } // WM_PAINT消息响应函数 void CSample01Frame::OnPaint() { CPaintDC dc(this); dc.TextOut(100, 100, "Hello World!"); } |
仍象编写Sample00程序一样建立一个Win32应用程序工程Sample01(配套程序见"光盘\配套程序\Sample01\"),然后分别向工程添加头文件Sample01.h和源文件Sample01.cpp,并将上述代码写入相应的文件。为了能顺利编译,还需要修改一下编译命令,通过"Alt+F7"快捷键呼出【Project Settings】对话框,在【Preprocessor definitions】栏的最后添加选项"_AFXDLL",前面用逗号分隔。接下来还需要在【Project Options】栏的最后添加命令行"/MD",用空格同其他命令行参数进行分隔。编译运行,可以看出效果同SDK方式编写的Sample00程序是一样的,但在代码实现上更加结构化,编写过程也更加简单。
接下来,对上述应用程序框架代码进行分析。首先从MFC应用程序的核心--CWinApp类的派生类CSample01App谈起。CWinApp类提供了可以获取消息并将获取到的消息分发到应用程序窗口的消息循环和一些关键的虚函数,通过对这些虚函数的重载可使开发人员对应用程序的一些固有行为进行扩展。当把头文件Afxwin.h包含进来后,就可以在程序中使用包括CWinApp在内的一些MFC类了。一个MFC应用程序有且只能有一个应用程序对象而且必须被以全局方式进行声明,所以该对象自程序开始运行起就一直驻留在内存。
由于使用了MFC应用程序框架的程序在本质上仍是Windows 应用程序,因此必然需要在程序中存在作为Windows 应用程序入口的WinMain()函数。在前面的示例代码中之所以没有看到WinMain()函数是由于该函数已经通过封装的手段隐藏到应用程序框架中了。除WinMain()外,CWinApp类成员函数Run()也是隐含执行的,这个函数也是非常重要的,它负责把消息放进应用程序窗口的消息循环中,由WinMain()函数完成对Run()的调用 。当WinMain()函数寻找到应用程序对象后将立即调用CWinApp类的虚函数InitInstance()。由于CWinApp基类是不知道究竟需要何种主框架窗口的,因此在使用时必须在CWinApp的派生类中对InitInstance()函数进行重载。InitInstance()函数是在应用程序已经开始运行但窗口尚未创建时被调用的,若非由InitInstance()创建了窗口,应用程序是无法拥有窗口的,这也就意味着缺少了InitInstance()函数的应用程序将无法接收、处理消息,对Windows程序而言这也就失去了存在的意义。由此可见,从CWinApp类中进行派生,并且对InitInstance()函数进行重载是编写MFC应用程序框架程序的必要条件。
除应用程序类外,从CFrameWnd派生的CSample01Frame类还对应用程序的主框架窗口做了描述。在构造函数中调用基类的CFrameWnd成员函数Create(),由Windows 负责创建出实际的窗口结构,并由应用程序框架将其链接到C++对象。
本示例程序的大部分功能实际是在MFC的CWinApp和CFrameWnd等基类中完成的,在编程时,只需在派生类中编写少量功能代码,C++允许以这样的方式借用基类中的大量代码而无须复制代码。应用程序框架负责提供程序的结构框架,开发人员在此基础上为其添加相应的实现代码,从而可以非常方便地完成一个完整的应用程序。应用程序框架不仅定义了应用程序的结构安排,实际上还包含了更多的C++基类。
4 小结 SDK的API编程方法、MFC的编程方法以及本系列讲座后面将要介绍的ATL编程方法是VC++程序设计中比较常用的几种编程方法,其中MFC以其强大的功能和灵活的编程方式而成为大多数程序开发人员最经常使用的一种编程方式。本文从基础问题入手对MFC及其框架程序做了较为详细的论述,使读者能够对MFC编程有一个基本的认识。
查看本文来源