摘要
本讲先来讨论对话框界面设计的一般过程和技巧,然后创建对话框类并用模式和无模式的方式来显示对话框。
对话框的界面设计过程
对话框是Windows应用程序中最重要的用户界面元素之一,它是通过对话框上的各种控件来和用户进行交互的。所谓"控件",是指具有一定功能的界面单元,如按钮、编辑框、列表框、组合框等。在这里,我们先来讨论对话框的界面设计过程。
1. 添加对话框资源
(1) 启动Visual Studio .NET,打开上一讲的单文档应用程序项目Viewer。
(2) 打开"项目"菜单,单击"添加资源",弹出"添加资源"对话框,如图1所示。
(3) 在该对话框中,"导入"按钮是从外部导入一个已有的资源,"自定义"是用来创建一个新的资源类型。在"资源类型"中选定"Dialog",然后单击"新建"按钮。这时"添加资源"对话框消失,回到Visual C++ .NET开发环境。可以看到,系统为对话框资源自动赋给它一个默认的标识名称IDD_DIALOG1,且有两个按钮:"确定"和"取消",在左侧对话框编辑器窗口中,还会自动弹出工具箱窗口。
(4) 单击工具箱窗口上的"
(5) 在对话框的空白处,单击鼠标,将会在属性窗口中显示出对话框资源的属性。图2所示的仅是展开"字体"属性的情形,可以看出:对话框属性有"外观"、"位置"、"行为"、"杂项"和"字体"。其中,对话框Caption(标题)属性在"外观"中,ID属性在"杂项"中,如图2所示。
(6) 保留默认的对话框资源ID号,在属性窗口中,将该对话框的标题内容改为"设置"。
2. 在对话框加添加和布置控件
在对话框中添加控件的方法有很多,这里我们推荐这样的方法:在"工具箱"窗口中,单击要添加的控件并按住鼠标不放,然后移动到对话框中,此时鼠标指针带有一个"+",在需要添加的位置处松开鼠标,这样就添加了该控件。一旦控件添加后,我们可以使用下列一些方法来布置控件。
第一个方法是使用网格和参照线。默认时对话框显示的是参照线,如图3所示,控件的位置一般不能超过参照线的范围,但我们可以通过对话框四周的尺寸柄来调整对话框的尺寸,同时参照线也会自动调整。单击对话框编辑器工具栏上的"网络"按钮
第二个方法是使用对话框编辑器工具栏。对话框编辑器工具栏上包含用于对话框控件布局的工具按钮,如图4所示,它与"格式"菜单下的菜单项命令相对应。
需要说明的是,
① 在使用布局命令之前,首先要选取要布局的控件,一般有好几个,称为控件组,这时只有一个控件周围有实心小方块(一般有八个),这个控件称为"主导控件",布局操作都是以这个"主导控件"为参照的。
② 选取多个控件的方法有两个。一是框选,即:拖动鼠标指针,在对话框中要选择的控件周围画一个选框。当释放鼠标按钮后,选框内和与该框相交的所有控件都被选定。二是单选,即先按住Ctrl或Shift键,然后单击要选择的控件。若按住的键是Shift,则再次单击已选定的控件,那么该控件被取消选定。
③ 当按住Ctrl键后,再单击控件,则该控件就是"主导控件"。
3. 为对话框创建一个类
要想显示和控制对话框,必须先为其创建一个对话框类,如下面的过程:
(1) 在对话框编辑器中,双击对话框的空白处,或右击对话框,弹出快捷菜单,单击"添加类",弹出"MFC类向导"对话框。
(2) 在"类名"框中,键入创建的类名CSetDlg,注意我们一般将大写字母C作为类名的第一个字符,以与其它标识符相区别。
(3) 从"基类"组合框中选择"CDialog"(MFC对话框类),结果如图5所示。其中,".h文件"和".cpp文件"用来指定新类的头文件和实现文件。单击
(4) 单击"完成"按钮,新的对话框类CSetDlg就创建好了。
模式和无模式对话框的显示
对话框有两种类型,一种是模式对话框,另一种是无模式对话框。所谓"模式对话框"是指当对话框显示后,用户必须在对话框中作出相应的操作,在退出对话框之前,对话框所在的应用程序不能执行其他操作。所谓"无模式对话框"是指当对话框被弹出后,一直保留在屏幕上,用户可继续在应用程序中进行其它操作。
1. 模式对话框的显示
一般情况下,我们看见的对话框多数是模式对话框。下面将前面的对话框以"模式"方式来显示。
(1) 将解决方案资源管理器窗口切换到"资源视图",双击Menu下的IDR_MAINFRAME,打开Viewer中的菜单资源。
(2) 在"格式"菜单中添加一个菜单项"背景设置(&B)…",其ID设为ID_FOMAT_SET。
(3) 由于该对话框用来设置视图的背景色,因此我们需将菜单项ID_FOMAT_SET的COMMAND事件映射添加在CViewerView类中,并在映射函数CViewerView::OnFormatSet中添加显示对话框代码,如图6所示。
程序说明:
① 程序中, DoModal()是CDialog的成员函数,用来负责模式对话框的显示和终止。
② 当对话框显示后,只有当用户单击"确定"按钮后,系统才认定用户在对话框中的选择或输入有效,函数DoModal返回IDOK,否则DoModal返回IDCANCEL,对话框中的选择或输入无效。
③ MessageBox是一个MFC窗口类CWnd的一个成员函数,用来显示一个"消息对话框",显示指定的内容。
(4) 在类CViewerView接口文件ViewerView.h的前面添加CSetDlg类的包含头文件,如图7所示的加框部分。
(5) 运行程序,打开"格式"菜单,单击"背景设置",结果如图7所示。由于我们还没有向对话框添加控件,因此显示的是一个默认的对话框。单击"确定"按钮后,还将弹出一个消息对话框,这就是上述代码的作用。
2. 无模式对话框的显示
无模式对话框与模式对话框的区别主要体现在:
① 模式对话框是由系统自动分配内存空间,在对话框退出时,对话框对象自动删除。而无模式对话框则需要用户来指定内存,退出时还需自己来删除对话框对象。
② 在退出时,无模式对话框与模式对话框所使用的终止函数是不一样的。模式对话框通过调用CDialog:: EndDialog来终止,而无模式对话框则是调用CWnd::DestroyWindow来终止的。
由于用户单击"确定"或"取消"按钮时,无论是模式还是无模式,对话框都将终止。因此对于无模式对话框来说,我们须在CDiaolog::OnOK()和CDiaolog::OnCancel()的函数重载中调用DestroyWindow()来退出对话框窗口,并且由于当用户单击"确定"时,对话框的输入数据有效,因此我们还需要在对话框退出之前调用CWnd::UpdateData来使输入有效(后面还要讨论)。下面就来操作。
(1) 将解决方案资源管理器窗口切换到"类视图",单击CSetDlg,然后在其属性窗口中单击"重写"按钮,这样属性窗口中就会列出了所有可重载的函数。
(2) 打开OnOK和OnCancel函数,添加它们的重载。图9是在其属性窗口中添加OnOK重载时的情形。
(3) 在OnOK和OnCancel函数中添加代码,如图10所示。
(4) 在CViewerView类中添加一个成员指针变量m_pSetDlg,变量类型为CSetDlg*。
(5) 在CViewerView类的析构函数中添加对该对话框指针的删除代码,如图11所示。
图11 在析构函数中添加删除代码
(6) 修改CViewerView::OnFormatSet代码,结果如图12所示。
(7) 运行程序,结果和模式对话框一样。问题是,如何获取无模式对话框中用户输入的数据呢?我们在下一讲中将加以讨论。