11.3.2 MFC程序的组织方式(1)
我们从第1章知道,在一行代码也不编写的情况下,使用Application Wizard就可以生成一个Windows程序。当然,该过程使用了MFC库。但不使用Application Wizard也完全可以编写出使用MFC的Windows程序。如果首先不求甚解地构造出最简单的基于MFC的程序,那么将对所涉及的基本元素有更清楚的认识。
使用MFC可以生成的最简单的程序,比本章前面使用原始Windows API编写的示例稍微简单一些。这次编写的示例将拥有一个窗口,但不在窗口内显示文本。这足以说明基本的组成部分,因此让我们试一试。
试一试:最简单的MFC应用程序
像以前多次做过的那样,使用File | New | Project菜单项创建一个新项目。这次不使用Application Wizard来创建基本的代码,因此选择Win32 Project作为该项目的模板,并在第二个对话框中选择Windows Application和Empty project选项。在创建该项目之后,从主菜单中选择Project | Ex11_02 properties,并在Configuration Properties的General子页上单击Use of MFC属性,将其属性值设置为Use MFC in a Shared DLL。
在这个已创建的项目中,可以创建一个新的源文件Ex11_02.cpp。为了在一个地方看到该程序的所有代码,可以将需要的类定义及类的实现都放在该文件中。为此,只需要在编辑窗口中手动添加代码即可-- 所需的代码不是很多。
首先,要添加一条包括afxwin.h头文件的#include语句,因为该文件包含许多MFC类的定义。这样,就可以从MFC中派生自己的类。
- #include <afxwin.h> // For the class library
要得到完整的程序,只需要从MFC中派生两个类即可:应用程序类和窗口类。我们甚至不需要像在本章前一个示例中那样编写WinMain()函数,因为该函数是由MFC库在后台自动提供的。看一看如何定义需要的这两个类。
1. 应用程序类
CWinApp类对任何使用MFC编写的Windows程序来说都很重要。该类的对象包括启动、初始化、运行和关闭应用程序所需的一切代码。需要根据CWinApp派生自己的应用程序类,从而得到自己的应用程序。我们将定义该类的专用版本以适应特定的应用需求。该派生类的代码如下所示:
- class COurApp: public CWinApp
- {
- public:
- virtual BOOL InitInstance();
- };
因为要实现一个简单的示例,所以这里不需要太多的特殊化工作。该类的定义中只有一个成员:InitInstance()函数。在基类中将该函数定义为虚函数,因此在派生类中它是一个重写函数;我们只是在为自己的应用程序类重新定义这个基类函数而已。该类中所有其他从CWinApp类继承的数据和函数成员都保持不变。
该应用程序类具有大量在基类中定义的数据成员,其中许多都对应于用作Windows API函数实参的变量。例如,成员m_pszAppName存储着指向定义应用程序名的字符串的指针。成员m_nCmdShow指定应用程序启动时以什么方式显示应用程序窗口。现在不必考虑所有继承的数据成员。在开发应用程序专用代码的过程中,将在需要使用这些成员时了解它们的用法。
在根据CWinApp派生自己的应用程序类时,必须重写虚函数InitInstance()。该函数的重写版本是由MFC为我们提供的WinMain()函数调用的,我们将在该函数中包括创建和显示应用程序窗口的代码。但在编写InitInstance()之前,应该先了解一下MFC库中定义窗口的类。
2. 窗口类
MFC应用程序需要一个窗口作为与用户交互的界面,称为框架窗口。需要为应用程序从MFC类CFrameWnd中派生一个窗口类,CFrameWnd类是专门为上述目的而设计的。因为CFrameWnd类提供了创建和管理应用程序窗口所需的一切,所以我们只需要给派生窗口类添加一个构造函数。构造函数允许指定窗口的标题栏,以适应应用程序的上下文:
- class COurWnd: public CFrameWnd
- {
- public:
- // Constructor
- COurWnd()
- {
- Create(NULL, _T("Our Dumb MFC Application"));
- }
- };
在构造函数中调用的Create()函数是从基类继承的。该函数创建一个窗口,并使该窗口附属于正被创建的COurWnd对象。注意,COurWnd对象与Windows显示的窗口不是一回事-- 类对象与物理窗口是截然不同的实体。
Create()函数的第一个实参值是NULL,表明我们希望为创建的窗口使用基类的默认属性。还记得吗?在本章前一个示例中需要直接使用Windows API定义窗口属性。第二个实参指定在窗口标题栏中使用的窗口名称。Create()函数还有其他参数,但那些参数都有完全令人满意的默认值,因此这里可以将它们全部忽略。