MFC Dlg

6.2  模态对话框

模态对话框独占了用户的输入,当一个模态对话框打开时,用户只能与该对话框进行交互,而其他用户界面对象收不到输入信息。应用程序用到的大部分对话框都是模态对话框。接下来这一节我们来详细地叙述模态对话框的创建过程。

【实例6-1】  创建模态对话框

光盘路径            /06/dialog_1/

实例目的            创建模态对话框

6.2.1  创建工程

*   在IDE中依次选择“File”→“New”菜单命令,或直接按快捷键“Ctrl+N”,打开“New”对话框。

*   在 “New”对话框中单击“Projects”选项卡,在列表框中选择“MFC AppWizard(.exe)”项,在“Project name”文本框中输入“dialog_1”,其他使用默认值,单击“OK”按钮,弹出“MFC AppWizard-Step1”对话框。

*   在“MFC AppWizard-Step1”对话框中,选中“Multiple Document”单选按钮,其他使用默认值,然后单击“Finish”按钮,在弹出的“New Project Information”对话框中单击“OK”按钮,就可以完成工程的创建。

这里创建工程的过程其实在前面已经提到过了,在这也就不太详细地描述了,接下来我们来看创建对话框资源的步骤。

创建对话框首先要创建对话框对应的资源。以下通过创建的工程“dialog_1”,具体地讲解如何运用对话框编辑器创建对话框资源的方法。

6.2.2  为应用程序添加对话框

*   打开dialog_1工程后,在IDE中依次选择“Insert”→“Resource”菜单,打开“Insert Resource”对话框,在“Resource type”属性框中选择Dialog选项,如图6-1所示。

*   然后单击“New”按钮,为程序添加一个新的对话框,并进入对话框编辑器,如图6-2所示。默认的对话框有“OK”和“Cancel”两个按钮,在窗口的旁边有一个控件面板,在控件面板上用鼠标选择一个控件,然后在对话框中单击,则相应的控件就被放置到了对话框模板中。

  

图6-1  添加资源对话框                        图6-2  对话框编辑界面

*   进入如图6-2所示的对话框编辑器后,可以看到IDE左侧工作区窗口的“Resource View”选项卡中列出的工程资源文件中添加了一个新的对话框ID。

6.2.3  修改对话框属性

为dialog_1添加新的对话框后,该对话框的属 性都是由IDE设置的默认值,因此接下来应当修改对话框的属性。将鼠标光标移动到对话框编辑器中需要编辑的对话框上,然后单击鼠标右键打开弹出式菜单,选 择“Properties”属性,打开“Dialog Properties”对话框,如图6-3所示。

对图6-3所示对话框的属性进行如下修改。

*   修改对话框ID,在“ID”输入框中输入“IDD_PASSWORD_DIALOG”。

*   修改对话框标题,在“Caption”输入框中输入“口令”。

*   为 了在中文系统下的美观,修改对话框字体。单击“Font”按钮,弹出“Select Dialog Font”对话框,在“Font”列表框中选择字体为“宋体”,在“Size”列表框中设置字号为10,单击“OK”确认退出“Select Dialog Font”对话框。

*   修改完毕后,如图6-4所示。

  

图6-3  对话框属性编辑对话框               图6-4  修改对话框属性编辑对话框

回车确认修改并退出“Dialog Properties”对话框。

*   打开“OK”和“Cancel”按钮的属性对话框,在“Caption”输入框中将标题分别改为“确认”和“取消”,并调整两个按钮的位置和对话框的大小,得到如图6-5所示的口令对话框。

图6-5  完成对话框属性的修改

6.2.4  在对话框中添加控件

依据实例要求,“确认”和“取消”按钮已经默认添加好了,只需要添加“请输入口令”输入框,并添加相应的说明。具体步骤如下。

*   在对话框中添加一个静态文本。在如图6-2所示的客户区右侧浮动的Control工具栏中的“Static Text”控件按钮上单击,然后在对话框资源中按下鼠标左键拖动,出现一个矩形框,松开鼠标左键,则在对话框资源中出现了一个“Static Text”控件。

另外,添加控件还可以利用将Control工具栏中 的控件直接拖到对话框资源中。单击对话框资源中的控件后,空间周围会出现一个虚线框,表示当前选中该控件。在控件中央按下鼠标左键不放可以将控件拖动到指 定位置,在虚线框上按下鼠标左键不放并拖动,可以调整控件的大小。按Delete键可以删除当前选中的空间。通过这些操作将添加的“Static Text”控件的位置和大小调整到如图6-6中虚线框的静态文本框控件所示位置和大小。

此时添加的“Static Text”控件,显示“Static”的字体。接着将鼠标移动到该控件上,单击鼠标右键,在弹出菜单中选择“Properties”,打开控件的属性编辑对话框,修改标题(在Caption输入框中)为“请输入口令:”如图6-7所示。

  

图6-6  在登录对话框中添加一个静态文本框           图6-7  修改静态文本框的属性

  在对话框中添加输入框(Edit Box),添加过程与 *   相同,但应当在Control工具栏中选择“Edit Box”控件的图标,将该控件调整到与图6-8所示虚线框选中的控件    一致。

打开控件属性编辑对话框,在ID输入框的ID改为IDC_PASSWORD_EDIT,然后在Styles选项卡中选中Password属性,将输入风格设置为口令风格,如图6-9所示。

  

图6-8  在登录对话框中添加一个输入框             图6-9 设置输入框的密码属性

  通过Dialog工具栏调整控件的位置。

  此外为了让对话框美观,读者也可以在对话框中用Static Text控件添加一些简要说明。

  设置对话框中各种控件的响应顺序,即运行时按下Tab键,输入焦点从一个控件换到另一个控件的顺序。

在对话框编辑界面中,可以通过选择主菜单“Layout”→“Tab Order”或者按快捷键“Ctrl+D”,进入Tab顺序的设置界面,此时对话框资源编辑器的客户区如图6-10所示。

设置Tab顺序是通过按所需的顺序依次单击各个控件完成,如进入图6-10所示的界面后,依次单击“请输入口令”输入框,“请输入口令”静态文本框,“确定”按钮和“取消”按钮,就可以设置成如图6-11所示的程序。

最后按Esc键,就可以确认修改并退出设置界面。

  

图6-10  设置对话框的响应顺序            图6-11  比较合适的登录对话框的Tab顺序

  在Dialog工具栏中单击“Test”按钮,或用快捷键“Ctrl+T”可以测试对话框,单击“确定”按钮或“取消”按钮,则退出测试状态。口令对话框的效果如图6-12所示。

6.2.5  创建对话框类

每一个对话框必须要和一个对话框类或其派生类相连才能发生作用。创建对话框类,即创建一个CDialog类的派生类与新建对话框资源关联。对话框类CDialog提供了访问控件属性,以及响应控件和对话框自身消息的功能。

6.2.6  创建对话框

创建与关联的对话框类的派生类的过程如下。

*   在 IDE主菜单栏中依次选择菜单“View”→“ClassWizard”,或者在开发环境的界面中直接使用快捷键“Ctrl+W”,打开 “ClassWizard”对话框。同时系统会检测到添加了新的对话框资源,并自动打开如图6-13所示的对话框,提示用户是否为新建的对话框添加一个对 话框类。

   

图6-12  口令对话框的效果       图6-13  提示用户为新添加的对话框创建一个对话框类

*   在如图6-14所示的对话框中,选中“Create a new class”单选项,为对话框资源创建一个新的类,单击“OK”按钮确认后打开如图6-14所示的“New Class”对话框。

图6-14  创建新类的对话框

*   在“New Class”对话框中为前面创建的实例dialog_1的会员登录对话框创建新的类。

— 在“Name”输入框中输入“CPasswordDialog”,表明新建类的名称为Cpassword Dialog。

— 此时“File name”输入框中的内容自动设置为“CPasswordDialog.cpp”,表明类的源文件为CPasswordDialog.cpp。

— 在“Base class”下拉列表框中选择“CDialog”,表明CPasswordDialog类的基类为CDialog。

— 单击“Dialog ID”下拉列表框中选择IDD_PASSWORD_DIALOG,表明Cpassword Dialog关联的对话框资源为IDD_PASSWORD_DIALOG。

— 单击“OK”按钮后,关闭New Class对话框,返回“ClassWizard”对话框,同时ClassWizard为登录对话框创建了一个新的类CPasswordDialog。 MFC类向导自动使类CPasswordDialog与IDD_PASSWORD_DIALOG模板联系起来。

6.2.7  为对话框类添加控件成员变量

对话框的主要功能是输出和输入数据,例子中的口令对话框的任务就是要在程序的开始要求用户输入口令,如果输入错误,则中断程序。对话框需要有一组成员变量来存储数据,而对话框中的控件是用来表示或输入数据的。

因此,存储数据的成员变量应该与控件相对应。与控件 对应的成员变量既可以是一个数据,也可以是一个控件对象,这将由具体需要来确定。例如,可以为一个文本框控件指定一个数据变量,这样就可以很方便地取得或 设置文本框控件所代表的数据。如果想对文本框控件进行控制,则应该为文本框指定一个CEdit对象,通过CEdit对象,程序员可以控制控件的行为。需要 指出的是,不同类的控件对应的数据变量的类型往往是不一样的,而且一个控件对应的数据变量的类型也可能有多种。

利用MFC类向导可以很方便地为对话框类CPasswordDlg加入成员变量。具体步骤如下。

*   在返回的“ClassWizard”对话框中单击“Member Variables”选项卡进入如图6-15所示的编辑对话框控件成员变量的界面。这个界面用于设置为控件关联变量,使得在程序中通过这些变量可以访问控件的属性。

该界面中的主要内容如下。

—  Project下拉列表框:选择需要编辑的工程名。

—  Class name下拉列表框:选择需要编辑的类名。

—  Control IDs列表框:列出对话框的控件及其对应的控件成员变量信息。其中有3列,“Control IDs”列给出了对话框的控件ID,“Type”列给出控件变量的类型,“Member”列给出控件变量的名称。选定某个控件,还可以编辑该控件对应的变 量。

—  Add Class按钮:添加新类。

—  Add Variable按钮:为选定的控件添加变量。

—  Delete Variable按钮:为选定的控件删除原来的变量。

—  Update Columns和Bind All按钮:跟数据库有关。

图6-15  ClassWizard编辑器对话框控件成员变量的界面

在如图6-15所示的“Project”下拉列表框 中已经默认选择dialog_1,在“Class name”下拉列表框中选择CLoginDialog,从Control IDs列表框中可以看到登录对话框中有3个控件,IDC_PASSWORD_EDIT、IDCANCEL和IDOK。需要获得用户输入的口令,因此需要为 IDC_LOGINNAME_EDIT添加变量。

  在图6-15所示的对话框的“Control IDs”列表框中选择IDC_LOGINNAME_EDIT,然后单击“Add Variable”按钮,打开如图6-16所示的添加成员变量对话框。

图6-16  添加成员变量对话框

— 在“Member variable name”输入框中输入m_Password,即将变量命名为m_Password。

— 在“Category”下拉列表框中选择“Value”,表明创建的变量是值,而不是控件。

— 在“Variable type”下拉列表框中选择CString,表明变量类型为CString。单击“OK”按钮,确认并返回ClassWizard对话框。如图6-17所示。

图6-17  完成变量添加的编辑成员变量的界面

  此 时可以看到,在“Control IDs”列表框中选择“IDC_LOGINNAME_EDIT”项后,在对话框的下方将出现该变量的属性介绍和说明。对于CString变量,还有一个 “Maximum Characters”输入框,用于设置IDC_LOGINNAME_EDIT输入框中的输入字符的个数。

  单击“ClassWizard”对话框中的“OK”按钮后,回到IDE主界面,完成变量的添加。

此时在IDE的左侧单击“Class View”选项卡,可以看到新建了一个类CPasswordDialog,展开CPasswordDialog节点,可以看到该类中添加了m_Password控件变量。

6.2.8  添加代码

实例dialog_1中要求口令对话框在程序运行一开始,程序框架还没有出现时弹出,所以在应用程序类的InitInstance()函数中进行口令的检查过程。下面就在程序中添加与口令对话框相应的代码。

*  在 工作区的ClassView标签中,依次选中“dialog_1 classes”→“CDialog_1App”→“InitInstance()”条目并双击,编译器自动定位到文件dialog_1.cpp中的 CDialog_1App:: InitInstance()函数的开头处。

*   在CDialog_1App::InitInstance()函数中增加以下代码:

BOOL CDialog_1App::InitInstance()

{

    AfxEnableControlContainer();

    ...

    Enable3dControlsStatic();       //Call this when linking to MFC statically

    #endif

        //进行口令询问过程

    CPasswordDialog m_Dlg;      //声明CPasswordDialog类的一个对象

    if(m_Dlg.DoModal()==IDOK)       //用户按下确定按钮

    {

        if(m_Dlg.m_Password!= "1234")

 

        {   //如果口令不对,则显示出错信息,结束程序

            MessageBox(NULL,"口令错误,口令必须为0~9999之间的整数,确定后将退出程                    序,","错误",

MB_OK|MB_ICONERROR);                   

return FALSE;

}

        else

        {

             AfxMessageBox("口令正确,谢谢使用!");

        }

 

    }

    else        //如果按下取消按钮,程序也结束

        return FALSE;

    ...

}

*   在文件dialog_1.cpp的头部,其他#include语句后添加下面的包含语句:

#include "PasswordDialog.h"

6.2.9  消息响应函数

MFC为对话框和控件定义了许多消息,可以通过“ClassWizard”对话框来查看、新建和删除相应的消息响应函数。下面在实例dialog_1的登录对话框中添加单击“登录”和“退出”两个按钮的消息处理函数,步骤如下。

*   在 IDE主菜单项中依次选择“View”→“ClassWizard”,打开ClassWizard对话框,选择“Member Maps”选项卡,在“Project”下拉列表框中选择dialog_1,在“Class name”下拉列表框中选择“CPasswordDialog”。

  在“Object IDs”下拉列表框中选择IDC_PASSWORD_EDIT。

  在Message项中选中消息EN_CHANGE,同时对话框的下部出现相应的提示。当Edit Box控件中的内容有改变时,就会发一个EN_CHANGE消息。

下面创建EN_CHANGE消息的响应函数,在该函数中,判断输入的是否是有效值。

  单 击“Add Function…”按钮,添加函数消息,单击“OK”按钮就可以创建一个名称为OnChangePasswordEdit的消息处理函数,单击 “Edit Code”按钮退出“ClassWizard”对话框,并自动打开PasswordDialog.cpp文件,且定位在 OnChangePasswordEdit()函数上。

为OnChangePasswordEdit()函数添加如下代码:

void CPasswordDialog::OnChangePasswordEdit()

{

// TODO: If this is a RICHEDIT control, the control will not

    // send this notification unless you override the CDialog::OnInitDialog()

    // function and call CRichEditCtrl().SetEventMask()

    // with the ENM_CHANGE flag ORed into the mask

    // TODO: Add your control notification handler code here

    //将控件中的数据传递给变量m_Password,并自动进行数据校验

    UpdateData(TRUE);

}

文本框:  
图6-18  添加了消息函数后的
     口令对话框效果图   编译、链接和运行程序,测试口令对话框的效果,如图6-18所示。

6.2.10  对话框的数据交换和检验机制

对话框的数据成员变量存储了与控件相对应的数据。数 据变量需要和控件交换数据,以完成输入或输出功能。例如,一个文本框既可以用来输入,也可以用来输出。用做输入时,用户在其中输入了字符后,对应的数据成 员应该更新;用做输出时,应及时刷新文本框的内容以反映相应数据成员的变化。对话框需要一种机制来实现这种数据交换功能,这对对话框来说是至关重要的。

MFC提 供了类CDataExchange来实现对话框类与控件之间的数据交换(DDX,Dialog Data Exchange),该类还提供了数据有效机制(DDV,Dialog Data Validity),即验证输入到对话框中的数据的有效性(例如,在本例中限制口令输入框的输入在0~9999之间的整数,那么当用户在其中输入了字符、 实数或大于9999的整数时,CDataExchange的DDV机制就会自动生成报错消息来提醒用户)。数据交换和数据有效机制适用于文本框、复选框、 单选按钮、列表框和组合框。在给每个控件连接相应变量时,ClassWizard同时自动完成了有关DDX和DDV的代码。数据交换的工作由 CDialog::DoDataExchange来完成。可在PasswordDialog.cpp文件中找到 CPasswordDlg::DoDataExchange函数。为其添加如下代码:

void CPasswordDialog::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CPasswordDialog)

    DDX_Text(pDX, IDC_PASSWORD_EDIT, m_Password);

    DDV_MinMaxInt(pDX,m_Password,0,9999);

    //}}AFX_DATA_MAP

}

MFC提供了处 理控件与控件变量之间的数据交换的机制,因此在代码中访问控件的属性,就可以直接通过访问控件变量进行。如实例dialog_1运行时,打开口令对话框, 在“请输入口令”输入框中输入整数,通过PasswordDialog::DoDataExchange()函数,m_Password就自动保存所有输 入的字符串值,反之如果程序运行时修改了m_Password,则通过PasswordDialog::DoDataExchange()函数,“请输入 口令”输入框就会显示m_Password的值。

这里需要注意,控件和控件变量之间的数据交换并非自 动完成的,即DoDataExchange()函数不是自动被调用的。例如在“会员名”输入框中输入字符串时,m_Password的值不随之改变,需要 调用CDialog::UpdateData()函数才能做到从控件到控件变量或者从控件变量到控件的数据传送。

CDialog::UpdateData()函数的原型为:

BOOL UpdateData( BOOL bSaveAndValidate = TRUE );

bSaveAndValidate参数用于指示数据传输的方向,TRUE表示从控件传给变量,FALSE表示从变量传给数据。

CDialog::UpdateData()函数的返回值用于确定操作是否成功,为FALSE表示不成功。

添加上述代码以后,我们再来看看程序的运行结果。运行程序弹出口令对话框,在“请输入口令”输入框中输入口令。假如我们输入的不是0~9999的整数的话就会出现如图6-19所示的提示框。这里我们在“请输入口令”文本框中输入的是“5678”。单击“确定”按钮。

同样地,输入别的不符合规定的错误口令也会弹出如图6-19所示的警告,只有当我们输入正确的口令“1234”时,才会弹出一个登录成功的对话框,如图6-20所示。

         

图6-19  在口令对话框中输入“5678”按“确认”按钮后的         图6-20  登录成功

6.2.11  创建弹出模态对话框的菜单

下面我们在前面创建的对话框中添加一个菜单项,下挂一个菜单,菜单命令的消息响应函数用来弹出一个模态对话框。

下面首先在菜单资源中添加菜单项和下拉菜单。

*   在工作区的Resource View标签中,双击“dialog_1 resource”→“Menu”→“IDR_dialog_1 TYPE”条目,打开菜单资源。

*   选中菜单资源中的“查看”菜单,弹出下拉的菜单,选中下面的一个空白菜单项。

*   单击鼠标右键,选中弹出菜单的Properties菜单命令,弹出属性对话框,单击其中的“Keep Visible”按钮,使属性对话框始终显示在前端。

*   选中General标签中的Separator,在菜单资源中添加一个分隔条,同时在最下面又自动产生一个空白菜单。

*   选中空白菜单,在属性对话框的General中输入ID_VIEW_MODALDIALOG,在Caption中输入“模态对话框(&M)…”,同时下面又会自动增加一个空白的菜单。

此时如果编辑、链接和运行程序,可以看到新增加的菜单项是灰色的。下面为刚刚创建的菜单项增加消息响应函数。

*   通 过菜单“View”→“ClassWizard”打开MFC ClassWizard对话框,在Class name项中选择CDialog_1View,在Object IDs中选择ID_VIEW_MODALDIALOG,在Message中选择消息COMMAND,单击“Add Function”按钮添加菜单命令的消息响应函数。函数名取默认值。

*   编辑、链接和运行程序,如图6-21所示。

下面我们在资源中增加一个对话框,将标识号设置为 IDD_MODAL_DIALOG,其中在对话框中添加一个静态的文本框,用来提示用户弹出的是一个模态的对话框,同样把“OK”按钮和“CANCEL” 按钮分别修改为“确定”和“取消”,然后创建相关类,类名为CDialogModal,头文件和源文件将会自动设置为CDialogModal.h和 CDialogModal.cpp。

创建好以后,下面将在dialog_1中显示该对话框,步骤如下。

*   在 工作区的ClassView标签中的“dialog_1 classes”→“CDialog_1View”→“OnView Modaldialog()”条目上双击,定位到CDialog_1View::OnViewModaldialog()函数处,在其中添加如下代码:

void CDialog_1View::OnViewModaldialog()

{

    //TODO:Add your command handler code here

    CDialogModal m_Dlg;     //创建对话框对象

    m_Dlg.DoModal();

}

上面的函数实际就是菜单命令“模态对话框…”的响应函数,通过ClassView也可以很快定位到该函数。

  在dialog_1View.cpp文件的头部,其他#include语句后添加下面的包含语句:

#include "DialogModal.h"

  编辑、链接和运行程序,测试模态对话框的效果,在如图6-21所示中单击“查看”→“模态对话框”,则弹出刚刚创建的新对话框,如图6-22所示。

         

图6-21  为菜单项增加消息响应函数                图6-22  弹出模态对话框

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值