|
1.2 示例本节给出了多个应用实例。1.2.1节介绍了如何在一个工作空间中包含多个工程;1.2.2节演示了如何增加消息映射;1.2.3节介绍了如何利用类向导关联成员变量;1.2.4节演示了一些调试技巧;1.2.5节演示了利用分隔窗口实现单文档多视图;1.2.6节演示了如何实现多文档。 1.2.1 新建工作空间本实例介绍了如何在一个工作空间中包含多个工程。 1.实例说明一个大的商业软件有几十个甚至几百个模块,划分这么多模块的优点至少有以下几个。 (1)便于维护。修改错误或新增功能只需要修改少量模块。 (2)复用性强。大的软件一般包含一个主程序和若干个工具,工具可以独立运行,是主程序的补充或简化。它们的内核是相同的,模块化使得他们可以共用内核。 (3)便于移植。由于与环境交互的部分都封装在对应模块中,环境变了,只需要修改对应的模块。举个例子,某软件以前只支持Access数据库,现在要支持Oracle,只需要修改与数据库交互的那个模块。 (4)便于分工协作。如果模块划分得不好,一个程序员无意中犯的错误,可能会导致其他程序员无法工作。 一般而言,一个模块对应一个工程,在新建工程时,会自动生成一个工作空间。如果想一个工作空间包含几个工程,可以用下面的方法。 2.实现下面的这个例子,演示如何让一个工作空间包含两个工程。具体步骤如下: (1)建立一个文件夹存放代码,如G:\VCBook。 (2)启动VC 6.0,选择菜单“File→New”命令打开“New”对话框,选择“Workspace”属性卡。在“Locatin”编辑框中输入Ex010201,在“Workspaces name”编辑框中输入Ex010201,如图1-38所示。单击“OK”按钮,完成新建工作空间。
图1-38 新建工作空间 (3)在Workspace窗口的工作空间(Workspace)名上单击鼠标右键(如图1-39所示),在弹出的快捷菜单上选择“Add New Project to Workspace”命令。
图1-39 增加工程 (4)在弹出的对话框的“Porject name”编辑框中输入Ex010201Exe,双击工程类型中的“MFC AppWizard(exe)”,在弹出的“MFC AppWizard-Step 1”对话框中选择“Dialog based”,直接单击“Finish”按钮完成新建工程。 (5)单击“File View”标签页,进入File View(文件视图)。重复步骤(2),在弹出对话框的“Project name”中输入Ex010201Dll,双击工程类型中的“MFC AppWizard(dll)”,在弹出的“MFC AppWizard - Step 1”对话框中选择“MFC Extension DLL(using shared MFC DLL)”,如图1-40所示,直接单击“Finish”按钮完成创建新工程。
图1-40 新建扩展动态库 (6)目前为止,已经新建了一个工作空间,包含两个工程。为了让Exe工程能够使用Dll中的内容,必须把它的输出路径调成一致。选择菜单“Project→Settings”命令(或使用快捷键Alt + F7),会弹出“Project Settings”对话框。选中Ex010201Dll工程,单击Link标签,将“Output file name”编辑框中的内容改成“../_Debug/Ex010201Dll.dll”,如图1-41所示。用同样的方法将“Ex010201Exe”的Output file name改成“../Debug/Ex010201Exe.exe”,单击“OK”按钮关闭“Project Setting”对话框。
图1-41 设置输出路径 (7)进入File View视图,在“Ex010201Dll files”上单击鼠标右键,在弹出的快捷菜单中选择“Set as Active Project”命令,将Ex010201Dll工程设为当前工程,如图1-42所示。从“Build”菜单中选择Build Ex010201Dll.dll命令。将Ex010201Exe设置成当前工程,从“Build”菜单中选择Execute命令创建并运行Ex010201Exe.exe。这时会在G:\VCBook\Ex010201\_Debug文件夹产生Ex010201Exe.exe和Ex010201Dll.dll。
图1-42 设置当前活动工程 (8)确保Ex010201Dll是当前工程,从“Insert”菜单中选择“New class”命令,会弹出“New class”对话框,如图1-43所示,在“Class type”下拉列表框中选择Generic Class,名称(Name)为CStudent,单击“OK”按钮。
图1-43 增加新类 (9)为CStudent类名前加__declspec(dllexport)以便于Ex010201Exe使用这个类。为CStudent类加一个私有成员m_iAge,公有函数SetAge。 Student.h的关键代码如下: class __declspec(dllexport) CStudent { public: bool SetAge(int iAge); CStudent(); virtual ~CStudent(); private: int m_iAge ; }; Student.cpp的关键代码如下: CStudent::CStudent() { } CStudent::~CStudent() { } bool CStudent::SetAge(int iAge) { m_iAge = iAge ; return true ; } (10)Ex010201Exe中重新声明CStudent类,与Ex010201Dll中的声明略有不同,并在CEx010201ExeDlg::OnInitDialog()使用CStudent。 class __declspec(dllimport) CStudent { public: bool SetAge(int iAge); CStudent(); virtual ~CStudent(); private: int m_iAge ; }; BOOL CEx010201ExeDlg::OnInitDialog() { CDialog::OnInitDialog(); CStudent stu ;
if(!stu.SetAge(100)) AfxMessageBox("设置学生年龄失败"); //… } (11)把Ex010201Exe设为当前工程,从“Project”菜单中选择“Dependencies”,在弹出的“Project Dependencies”对话框中把唯一的一个复选框选上,如图1-44所示。设置成功后,Ex010201Dll会依赖于Ex010201Exe,编译Ex010201Exe时会自动编译Ex010201Dll。
图1-44 设置依赖关系 (12)创建并运行Ex010201Exe.exe,查看效果。 (13)SetAge这个函数写得极端不合理,因为学生的年龄是有一个范围的,不可以是0也不可能是100。这里不研究实际范围,假定最小年龄是5,最大年龄是50。那么SetAge函数应该这样写: bool CStudent::SetAge(int iAge) { if(iAge < 5 || iAge > 50 ) return false ;//设置失败 m_iAge = iAge ; return true ; } 只编译Ex010201.dll,运行Ex010201Exe.exe,查看效果,效果如图1-45所示。
图1-45 Ex010201Exe.exe运行效果 这个示例体现了模块化的优点,修改了一个模块,不影响其他模块。 注意: (1)如是一个模块变化较大,声明部分发生了变化,使用此模块的其他模块也必须重新编译。 (2)将多个工程放进一个工作空间只是便于编写代码,当工程比较多时只需要将几个常用工程放进工作空间。
|
|