前面几节讲了属性页对话框,我们可以根据所讲内容方便的建立自己的属性页对话框。本节讲解Windows系统中最常用最简单的一类对话框–消息对话框。

我们在使用Windows系统的过程中经常会见到消息对话框,提示我们有异常发生或提出询问等。因为在软件开发中经常用到消息对话框,所以MFC提供了两个函数可以直接生成指定风格的消息对话框,而不需要我们在每次使用的时候都要去创建对话框资源和生成对话框类等。这两个函数就是CWnd类的成员函数MessageBox()和全局函数AfxMessageBox()。

一.CWnd::MessageBox()函数和AfxMessageBox()函数的用法

下面就分别讲解两个函数的用法。

1.CWnd::MessageBox()函数

CWnd::MessageBox()的函数原型如下:

int MessageBox(
           LPCTSTR lpszText,
           LPCTSTR lpszCaption = NULL,
           UINT nType = MB_OK 
       );

参数说明:
lpszText:需要显示的消息字符串。
lpszCaption:消息对话框的标题字符串。默认值为NULL。取值为NULL时使用默认标题。
nType:消息对话框的风格和属性。默认为MB_OK风格,即只有“确定”按钮。
nType的取值可以是下面两个表中任取一个值,也可以是各取一个值的任意组合。即可以指定一个对话框类型,也可以指定一个对话框图标,还可以两者都设定。

MFC---消息对话框和文件对话框(对话框)_文件对话框

对话框类型表

MFC---消息对话框和文件对话框(对话框)_模态_02

对话框图标表

如果想要设置nType的值为类型和图标的组合,可以像这样取值:MB_OKCANCEL | MB_ICONQUESTION。按位取或就可以了。

2.AfxMessageBox()函数

AfxMessageBox()的函数原型为:
       int AfxMessageBox(
           LPCTSTR lpszText,
           UINT nType = MB_OK,
           UINT nIDHelp = 0 
       );

参数说明:
lpszText:同CWnd::MessageBox()函数
nType:CWnd::MessageBox()函数
nIDHelp:此消息的帮助的上下文ID。默认值为0,取0时表示要使用应用程序的默认帮助上下文。

二.CWnd::MessageBox()和AfxMessageBox()的返回值

我们在调用了上面两个函数后,都可以弹出模态消息对话框。消息对话框关闭后,我们也都可以得到它们的返回值。两者的返回值就是用户在消息对话框上单击的按钮的ID,可以是以下值:
IDABORT:单击“终止”按钮。
IDCANCEL:单击“取消”按钮。
IDIGNORE:单击“忽略”按钮。
IDNO:单击“否”按钮。
IDOK:单击“确定”按钮。
IDRETRY:单击“重试”按钮。
IDYES:单击“是”按钮。

三.应用举例

我们还是拿前面加法计算器的程序做例子。

大家是否记得,在模态对话框及其弹出过程中我们修改了CAdditionDlg::OnBnClickedAddButton()函数,在点了“计算”按钮以后先弹出了一个模态对话框,询问用户是否确定要进行加法计算,并通过模态对话框DoModal函数的返回值判断用户选择了“确定”还是“取消”。这些功能很明显消息对话框完全能够实现,现在就使用消息对话框来替代原来的模态对话框。

在非模态对话框的创建及显示中,注释了模态对话框的相关代码,加入了非模态对话框的创建和显示代码,我们在加入消息对话框之前将非模态对话框的代码也注释或删除掉,确保此函数中不再生成原来的模态对话框或非模态对话框。

修改后的CAdditionDlg::OnBnClickedAddButton()函数如下:

void CAdditionDlg::OnBnClickedAddButton()   
{   
    // TODO: Add your control notification handler code here   
  
    INT_PTR nRes;   
   
    // 显示消息对话框   
    nRes = MessageBox(_T("您确定要进行加法计算吗?"), _T("加法计算器"), MB_OKCANCEL | MB_ICONQUESTION);   
    // 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行   
    if (IDCANCEL == nRes)   
        return;   
   
    // 将各控件中的数据保存到相应的变量   
    UpdateData(TRUE);   
   
    // 将被加数和加数的加和赋值给m_editSum   
    m_editSum = m_editSummand + m_editAddend;   
   
    // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    UpdateData(FALSE);   
    // 设置属性对话框为向导对话框   
    //sheet.SetWizardMode();   
}

编译运行,在运行结果对话框上点“计算”按钮弹出以下消息对话框:

MFC---消息对话框和文件对话框(对话框)_编辑框_03

大家也可以将MessageBox函数换为AfxMessageBox()函数,同时参数进行相应修改,运行下看看效果。

消息对话框就讲到这里了。在以后的软件开发中用到它的频率很高,希望大家慢慢熟悉并掌握它。

上一讲介绍的是消息对话框,本节讲解文件对话框。文件对话框也是很常用的一类对话框。

文件对话框的分类

文件对话框分为打开文件对话框和保存文件对话框,相信大家在Windows系统中经常见到这两种文件对话框。例如,很多编辑软件像记事本等都有“打开”选项,选择“打开”后会弹出一个对话框,让我们选择要打开文件的路径,这个对话框就是打开文件对话框;除了“打开”选项一般还会有“另存为”选项,选择“另存为”后往往也会有一个对话框弹出,让我们选择保存路径,这就是保存文件对话框

正如上面举例说明的,打开文件对话框用于选择要打开的文件的路径,保存文件对话框用来选择要保存的文件的路径。

文件对话框类CFileDialog

MFC使用文件对话框类CFileDialog封装了对文件对话框的操作。CFileDialog类的构造函数原型如下:

explicit CFileDialog(
   BOOL bOpenFileDialog,
   LPCTSTR lpszDefExt = NULL,
   LPCTSTR lpszFileName = NULL,
   DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
   LPCTSTR lpszFilter = NULL,
   CWnd* pParentWnd = NULL,
   DWORD dwSize = 0,
   BOOL bVistaStyle = TRUE
);

参数说明:
bOpenFileDialog:指定要创建的文件对话框的类型。设为TRUE将创建打开文件对话框,否则将创建保存文件对话框。

lpszDefExt:默认的文件扩展名。如果用户在文件名编辑框中没有输入扩展名,则由lpszDefExt指定的扩展名将被自动添加到文件名后。默认为NULL。

lpszFileName:文件名编辑框中显示的初始文件名。如果为NULL,则不显示初始文件名。

dwFlags:文件对话框的属性,可以是一个值也可以是多个值的组合。关于属性值的定义,可以在MSDN中查找结构体OPENFILENAME,元素Flags的说明中包含了所有属性值。默认为OFN_HIDEREADONLY和OFN_OVERWRITEPROMPT的组合,OFN_HIDEREADONLY表示隐藏文件对话框上的“Read Only”复选框,OFN_OVERWRITEPROMPT表示在保存文件对话框中如果你选择的文件存在了,就弹出一个消息对话框,要求确定是否要覆盖此文件。

lpszFilter:文件过滤器,它是由若干字符串对组成的一个字符串序列。如果指定了文件过滤器,则文件对话框中只有符合过滤条件的文件显示在文件列表中待选择。给大家看看VS2010 MSDN中给出的一个例子:

static TCHAR BASED_CODE szFilter[] = _T("Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files (*.*)|*.*||");

这样设置过滤器以后,文件对话框的扩展名组合框中将有四个选项:Chart Files (.xlc)、Worksheet Files (.xls)、Data Files(.xlc;.xls)和All Files (.),大家可以看到每种文件的扩展名规定都是一个字符串对,例如Chart Files的过滤字符串是Chart Files(.xlc)和.xlc成对出现的。

pParentWnd:文件对话框的父窗口的指针。

dwSize:OPENFILENAME结构体的大小。不同的操作系统对应不同的dwSize值。MFC通过此参数决定文件对话框的适当类型(例如,创建Windows 2000文件对话框还是XP文件对话框)。默认为0,表示MFC将根据程序运行的操作系统版本来决定使用哪种文件对话框。

bVistaStyle:指定文件对话框的风格,设为TRUE则使用Vista风格的文件对话框,否则使用旧版本的文件对话框。此参数仅在Windows Vista中编译时适用。

文件对话框也是模态对话框,所以在打开时也需要调用CFileDialog类的DoModal()成员函数。在打开文件对话框中点了“打开”或者在保存文件对话框中点了“保存”以后,我们可以使用CFileDialog类的成员函数GetPathName()获取选择的文件路径。

下面列出几个CFileDialog类的成员函数,我们可以使用它们获得文件对话框中的各种选择。

GetFileExt():获得选定文件的后缀名。
GetFileName():获得选定文件的名称,包括后缀名。
GetFileTitle():获得选定文件的标题,即不包括后缀名。
GetFolderPath():获得选定文件的目录。
GetNextPathName():获得下一个选定的文件的路径全名。
GetPathName():获得选定文件的路径全名。
GetReadOnlyPref():获得是否“以只读方式打开”。
GetStartPosition():获得文件名列表中的第一个元素的位置。

文件对话框实例

根据前面所讲内容,给大家做个文件对话框实例。
1.创建一个基于对话框的MFC应用程序工程,名称设为“Example17”。

2.修改主对话框IDD_EXAMPLE17_DIALOG的模板,删除自动生成的“TODO: Place dialog controls here.”静态文本框,添加两个编辑框,ID分别为IDC_OPEN_EDIT和IDC_SAVE_EDIT,再添加两个按钮,ID分别设为IDC_OPEN_BUTTON和IDC_SAVE_BUTTON,Caption分别设为“打开”和“保存”。按钮IDC_OPEN_BUTTON用于显示打开文件对话框,编辑框IDC_OPEN_EDIT显示在打开文件对话框中选择的文件路径。按钮IDC_SAVE_BUTTON用于显示保存文件对话框,编辑框IDC_SAVE_BUTTON显示在保存文件对话框中选择的文件路径。

3.分别为按钮IDC_OPEN_BUTTON和IDC_SAVE_BUTTON添加点击消息的消息处理函数CExample17Dlg::OnBnClickedOpenButton()和CExample17Dlg::OnBnClickedSaveButton()。

4.修改两个消息处理函数如下:

void CExample17Dlg::OnBnClickedOpenButton()   
{   
    // TODO: Add your control notification handler code here   
    // 设置过滤器   
    TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||");   
    // 构造打开文件对话框   
    CFileDialog fileDlg(TRUE, _T("txt"), NULL, 0, szFilter, this);   
    CString strFilePath;   
   
    // 显示打开文件对话框   
    if (IDOK == fileDlg.DoModal())   
    {   
        // 如果点击了文件对话框上的“打开”按钮,则将选择的文件路径显示到编辑框里   
        strFilePath = fileDlg.GetPathName();   
        SetDlgItemText(IDC_OPEN_EDIT, strFilePath);   
    }   
}   
   
   
void CExample17Dlg::OnBnClickedSaveButton()   
{   
    // TODO: Add your control notification handler code here   
    // 设置过滤器   
    TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|Word文件(*.doc)|*.doc|所有文件(*.*)|*.*||");   
    // 构造保存文件对话框   
    CFileDialog fileDlg(FALSE, _T("doc"), _T("my"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, this);   
    CString strFilePath;   
   
    // 显示保存文件对话框   
    if (IDOK == fileDlg.DoModal())   
    {   
        // 如果点击了文件对话框上的“保存”按钮,则将选择的文件路径显示到编辑框里   
        strFilePath = fileDlg.GetPathName();   
        SetDlgItemText(IDC_SAVE_EDIT, strFilePath);   
    }   
}

上面显示编辑框内容时,使用了Windows API函数SetDlgItemText,当然也可以先给编辑框关联变量,然后再使用在创建对话框类和添加控件变量中介绍的CDialogEx::UpdateData()函数,但是我比较习惯使用SetDlgItemText函数,感觉比较灵活。

5.运行此程序,在结果对话框上点“打开”按钮,显示打开文件对话框如下:

MFC---消息对话框和文件对话框(对话框)_mfc_04

点“保存”按钮后,显示保存文件对话框:

MFC---消息对话框和文件对话框(对话框)_模态_05

在打开文件对话框和保存文件对话框都选择了文件路径后,主对话框如下:

MFC---消息对话框和文件对话框(对话框)_mfc_06

到此,文件对话框就讲完了,是不是依然很简单?如果忘记了文件对话框类构造函数的参数意义,可以回来看看或者在MSDN上查阅。