一、何为对话框
- 是Windows应用程序中最重要的用户界面元素之一,是与用户交互的重要手段。
- 是一个特殊类型的窗口,可作为各种控件(具有独特功能的界面元素)的容器,可用于捕捉和处理用户的多个输入信息或数据。
二、创建对话框
情形一:直接创建一个基于对话框的应用程序
情形二:在一个应用程序中添加对话框资源并创建对话框类
- 下面主要讲述第二种情形,其中应用程序以单文档应用程序为例。
1. 创建步骤
添加对话框资源 + 创建对话框类
2. 资源&资源标识
- Visual C++ 6.0将Windows应用程序中经常用到的菜单、工具栏、对话框、图标等都视为“资源”,并将其单独存放在一个资源文件(第4课有提及)中。
- 每个资源都有相应的标识符(即ID)来区分,并且可以像变量一样进行赋值。
常用资源分类:快捷键列表、对话框、图标、菜单、字符串表、工具栏按钮、版本信息
常用资源的类别 | 说明 |
快捷键列表(Accelerator) |
一系列组合键的集合,被应用程序用来引发一个动作。 该列表一般与菜单命令相关联,用来代替鼠标操作。 |
对话框(Dialog) | 含有按钮、列表框、编辑框等各种控件的窗口 |
图标(Icon) |
代表应用程序显示在Windows桌面上的位图 它同时有32x32像素和16x16像素两种规格 |
菜单(Menu) | 用户通过菜单可以完成应用程序的大部分操作 |
字符串表(String Table) | 应用程序使用的全局字符串或其他标识符 |
工具栏按钮(Toolbar) |
工具栏外观是以一系列具有相同尺寸的位图组成的 它通常与一些菜单命令项相对应,以提高用户的工作效率 |
版本信息(Version) | 包含应用程序的版本、用户注册码等相关信息 |
除了上述常用资源类别外,还有鼠标指针、HTML等,甚至可以自己添加新的资源类别。
每一个资源类别下都有一个或多个相关资源,每一个资源均是由标识符来定义的。
当添加一个新的资源对象时,系统会为其提供默认的标识符名称,如IDD_DIALOG1等。当然,用户可以重命名。
3. 添加对话框资源
假设我们为当前应用程序Ex_SDI添加了一个对话框资源,系统为其提供的默认的标识符名称为IDD_DIALOG1。
使用通用的对话框模板创建的对话框资源,有“确定”和“取消”两个按钮,这两个按钮的标识符分别为IDOK和IDCANCEL。
4. 创建对话框类
添加完对话框资源,我们要想在应用程序中使用该对话框,必须先为该对话框模板创建一个用户对话框类:为对话框资源创建一个新类→类名以C字母打头(假设为COneDlg)→一个基于对话框资源模板IDD_DIALOG1的用户对话框类COneDlg就创建好了
- 注:用户对话框类是从基类CDialog(第三课有提及)派生而来的
3、4节的结果:为应用程序Ex_SDI添加了一个新对话框资源IDD_DIALOG1,并为之生成了一个对话框类COneDlg。
三、设计对话框
1. 控件的添加和布局
- 控件工具栏+控件布局工具栏
- 所有静态控件的ID均默认为IDC_STATIC(好像控件那一课将会学到...)
2. WM_INITDIALOG消息
定义:在对话框显示之前向父窗口发送的消息
我们建立了此消息和OnInitDialog函数的关联,即OnInitDialog函数是WM_INITDIALOG消息的映射,因此系统在对话框显示之前就会调用OnInitDialog函数(故常将对话框一些初始化代码添加到OnInitDialog函数中)
注:Visual C++只会为基于对话框的应用程序添加WM_INITDIALOG消息的映射函数OnInitDialog,并添加了一系列的初始化代码。但在应用程序添加的对话框资源,创建的对话框类并不会自动添加该消息的映射函数,这需要手动操作。
下面以单文档应用程序Ex_SDI添加的COneDlg对话框为例说明该映射过程:MFC ClassWizard对话框(Message Maps选项卡)→类名选定为COneDlg(Objects IDs选定为COneDlg)→双击Messages列表框中的(要映射的)WM_INITDIALOG消息→在CEx_SDIView类中添加该消息的映射函数OnInitDialog→双击消息函数(即OnInitDialog)定位到COneDlg::OnInitDialog函数实现的源代码处
四、使用对话框
1. 步骤概述
- 先在应用程序中添加该对话框类的包含头文件(在Ex_SDIView.cpp中添加#include "OneDlg.h");
- 然后定义该类的对象(COneDlg dlg;);
- 通过对象调用类的成员函数DoModal来模式显示,或通过对象指针来创建对话框。
注:DoModal是CDialog基类虚成员函数,它用来显示和终止模式对话框。
2. 在程序中使用
- 方法:将显示对话框的代码添加到命令消息的映射函数中
由于单文档应用程序包含菜单的用户界面,因而通常将代码添加到菜单命令消息的映射函数中。
过程:将项目工作区窗口切换到ResourceView选项卡→双击资源Menu项中的IDR_MAINFRAME(打开菜单编辑器)→完成输入新的菜单项(假设其ID为ID_DLG_FIRST)→MFC ClassWizard对话框(Messaage Maps选项卡)→类名选定为CEx_SDIView(Objects IDs选定为ID_DLG_FIRST)→双击Messages列表框中的(要映射的)COMMAND消息→在CEx_SDIView类中添加该消息的映射函数OnDlgFirst(该成员函数是对菜单项ID_DLG_FIRST的映射)→双击消息函数OnDlgFirst定位到CEx_SDIView::OnDlgFirst函数实现的源代码处→添加如下代码→在CEx_SDIView类的实现文件Ex_SDIView.cpp中添加COneDlg类的头文件包含→编译并运行(点击菜单项会显示对话框)
void CEx_SDIView::OnDlgFirst() { // TODO: Add your command handler code here COneDlg dlg; dlg.DoModal(); }
3. DoModal和模式对话框
模式对话框:对话框弹出后,用户必须在对话框中作出相应的操作,在退出对话框之前,对话框所在的应用程序不能继续执行。
模式对话框中的“确定”和“取消”按钮:单击确定按钮,系统认定用户在对话框中的选择或输入有效,对话框退出;单击取消按钮,对话框中的选择或输入无效,退出对话框,程序恢复原有状态。
将对话框以模式方式来显示:通过CDialog::DoModal函数来实现
- DoModal函数:没有形参,但有返回值。单击确定按钮,则DoModal结束并返回默认的IDOK值(IDOK是确定按钮的ID值);单击取消按钮,DoModal结束并返回默认的IDCANCEL值(IDCANCEL是取消按钮的ID值);若有错误,则返回-1。
即要求获取对话框中用户操作的内容,还要判断DoModal的返回值。
即使用类似这样的代码:int nRet = dlg.DoModal();
4. 通用对话框
从上面的过程可知,使用对话框编辑器和MFC ClassWizard可以创建自己的对话框类。
除此,在Visual C++ 6.0中还提供了一些通用对话框供用户在程序中直接调用。
这些对话框都是Windows标准用户界面对话框,MFC为它们提供了相应的MFC类。MFC对这些通用对话框所构造的类都是从一个公共的基类CCommonDialog派生而来的。下标列出了MFC的通用对话框类:
对话框 | 用途 |
CColorDialog | 颜色对话框,用来选择或创建颜色 |
CFileDialog | 文件对话框,用来打开或保存一个文件 |
CFindReplaceDialog | 查找替换对话框,用来查找或替换指定字符串 |
CPageSetupDialog | 页面设置对话框,用来设置页面参数 |
CFontDialog | 字体对话框,用来从列出的可用字体中选择一种字体 |
CPrintDialog | 打印对话框,用来设置打印机的参数及打印文档 |
这些对话框的共同特点:都只从用户获取信息,但并不对信息作处理。例如,文件对话框可用来选择一个要打开的文件,但它实际上只是给程序提供了一个文件路径名,用户的程序必须调用相应的成员函数才能打开文件。类似地,字体对话框只是填充一个描述字体的逻辑结构,但它并不创建字体。
用户可以在程序中直接使用这些通用对话框,例如,可将下面的代码添加在前面Ex_SDI项目CEx_SDIView::OnDlgFirst函数中,运行后点击菜单项会弹出一个文件对话框,选定一个文件并单击“打开”按钮,就会弹出一个消息对话框,显示该文件的全路径名。
void CEx_SDIView::OnDlgFirst() { // TODO: Add your command handler code here CString filter; filter = "文本文件(*.txt)|*.txt | C++文件(*.h,*.cpp)|*.h;*.cpp ||"; CFileDialog dlg (TRUE, NULL, NULL, OFN_HIDEREADONLY, filter); if (dlg.DoModal() == IDOK) { CString str, str1; str = dlg.GetPathName(); //返回选择文件的路径 AfxMessageBox(str); } }
- 上述代码中,CString是MFC中的一个类,用来操作字符串。
通用文件对话框类CFileDialog的构造函数的原型如下:
CFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd *pParentWnd = NULL);
参数中:
- 当bOpenFileDialog为TRUE时,表示文件打开对话框,为FALSE时表示文件保存对话框。
- lpszDefExt用来指定文件扩展名,若用户在文件名编辑框中没有输入扩展名,则系统在文件名后自动添加lpszDefExt指定的扩展名。
- lpszFileName用来在文件名编辑框中指定开始出现的文件名,若为NULL时,则不出现。
- dwFlags用来指定对话框的界面标志,当为OFN_HIDEREADONLY时表示隐藏对话框中的“只读”复选框,当为OFN_OVERWRITEPROMPT时表示文件保存时,若指定的文件有重名,则出现提示对话框。
- pParentWnd用来指定对话框的父窗口指针。
- lpszFilter参数用来确定出现在文件列表框中的文件类型。它由一对或多对字符串组成,每对字符串中第一个字符串表示过滤器名称,第二个字符串表示文件扩展名,若指定多个扩展名则用“;”分隔,字符串最后用两个“|”结尾。
函数原型中,LPCTSTR类型(第2课提到的LPCSTR表示const char *)用来表示一个常值字符指针,这里可以将其理解为一个常值字符串类型。
GetPathName是CFileDialog类成员函数,用来获取文件的全路径名。除此,CFileDialog类中还有类似的成员函数:
//返回在对话框确定的文件名 CString GetFileName() const; //返回在对话框中确定的文件扩展名 CString GetFileExt() const;
- 强调:当只调用对话框类的成员函数DoModal并返回IDOK后,该对话框类的其他属性成员函数才会有效。
注:关于其他通用对话框的具体用法在以后的章节中将陆续介绍。
5. 消息对话框
定义:是最简单的一类对话框,只是用来显示信息的。
在Visual C++ 6.0的MFC类库中就提供相应的函数实现这样的功能,使用时,直接在程序中调用它们即可。
它们的函数原型如下:
int AfxMessageBox(LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0); int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK);
这两个函数都是用来创建和显示消息对话框的,它们和第一课使用到的Win32 API函数MessageBox是不同的,前者是MFC类库中的函数。AfxMessageBox是全程函数,可以用在任何地方。而MessageBox只能在控件、对话框、窗口等一些窗口类中使用。
这两个函数都返回用户选择按钮的情况,如返回IDOK表示用户单击OK按钮。
参数lpszText表示在消息对话框中显示的字符串文本;lpszCaption表示消息对话框的标题,为NULL时使用默认标题;nIDHelp表示消息的上下文帮助ID标识符;nType表示消息对话框的图标类型以及所包含的按钮类型,这些类型都是用MFC预先定义的一些标识符来指定的,例如MB_ICONSTOP、MB_YESNOCANCEL等,具体见下图:
注:图标类型和按钮类型的标识可使用按位或运算符“|”来组合。
例如,下面是消息对话框的使用示例:
int nChoice = MessageBox("你喜欢周帅帅吗?", "爱情问卷", MB_YESNO|MB_ICONQUESTION); if (nChoice == IDYES) AfxMessageBox("QQ914408090 TEL15195952087");