第11章对话框及常用控件
对话框在Windows程序中是用户和Windows程序交互的主要途径。对话框操作简单方便,既可以是最简单的消息框,也可以是复杂的数据输入表单等。控件是一种特殊的子窗口,通常用户是具体通过对话框中的各种控件来和Windows程序交互的。
本章主要内容包括:对话框的创建、使用和销毁,模式对话框和无模式对话框的概念,对话框数据交换和验证机制,MFC通用对话框类、常用控件使用方法以及MFC 简单数据类型使用方法。
11.1对话框的创建与使用
对话框是一个能接收消息的窗口,用户可以移动、缩放和关闭对话框。在一个对话框中通常可以包含许多称为控件的元素,例如:静态文本、编辑框、按钮、列表框、组合框、树形视图、以及进度指示器等。MFC对这些控件进行了封装,同时提供对话框数据交换和校验机制,用来实现控件数据的初始化,以及从控件中获取用户的输入数据。
MFC中的CDialog类封装了Windows对话框的基本功能,是所有对话框的基类。CDialog类是CWnd类的派生类,该类的定义在“afxwin.h”文件中。
11.1.1对话框的创建
创建和使用一个对话框的步骤一般包括:
(1)创建对话框资源;
(2)设置对话框及控件属性;
(3)创建对话框派生类;
(4)为控件添加成员变量;
(5)为控件添加消息处理函数;
(6)在程序中创建对话框派生类的对象;
(7)调用DoModal或Create显示对话框。
【例11.1】创建一个SDI类型的工程CompArea,要求添加菜单“计算”及其菜单项“三角形面积”,并为该菜单项添加函数体为空的命令消息处理函数。
操作步骤为:
①打开Visual C++集成开发环境,单击File|New菜单项,打开New对话框。
②在New对话框中选择Projects标签,输入工程名为“CompArea”,本例的保存路径为“E\Samples”,单击“OK”按钮。
③在“MFC AppWizard-step 1”对话框中选择“Single document”,其余步骤中均使用默认选项,生成一个SDI工程。
④在工作区中选择ResourceView标签,展开Menu项,在IDR_MAINFRAME 上双击鼠标左键启动菜单资源编辑器。
⑤用鼠标将顶层菜单最右边的虚方框拖至“查看”和“帮助”之间。在虚方框上双击鼠标左键,弹出Menu Item Properties对话框,在General标签的Caption编辑框中输入菜单标题:计算(&C),其中“&”的作用是使其后的字符加上下划线,从而可以让用户用键盘来选择菜单。Pop-up检查框默认选中,表明新加的菜单可以有其弹出的子菜单。如图11.1所示。
图11.1 添加新菜单
⑥将Menu Item Properties对话框左上角的“图钉”状按钮按下,使该对话框保持可见。用鼠标左键单击“计算”菜单下的虚方框,在新显示的Menu Item Properties 对话框中设置要添加的菜单项的属性。如图11.2所示,设置ID为“ID_COMPUTER_TRIANGLE”,设置Caption为“三角形面积”。
图11.2 添加菜单项“三角形面积”及设置属性
⑦在工具栏单击存盘图标(或者按Ctrl+S键)将资源文件ComputerArea.rc存盘,关闭菜单项属性窗口以及菜单编辑器窗口。
⑧选择View|ClassWizard…菜单项,弹出MFC ClassWizard对话框,选择Message Maps标签,在Class name组合框中选择视图类CCompAreaView,在Object IDs列表
框中选择ID_COMPUTER_TRIANGLE,在Messages列表框中的COMMAND上双击鼠标左键,弹出Add Member Function对话框。如图11.3所示。
图11.3 添加菜单消息处理函数
⑨采用默认函数名OnComputerTriangle,单击OK按钮关闭Add Member Function 对话框,返回MFC ClassWizard对话框,在Member functions列表框中可见新添加的成员函数OnComputerTriangle。
⑩在Member functions列表框中的OnComputerTriangle函数名上双击,编译器自动关闭MFC ClassWizard对话框,并在客户区打开CompAreaView.cpp文件,定位至OnComputerTriangle函数,此时该函数体为空。
?至此就完成了添加菜单“计算”及其菜单项“三角形面积”,并为该菜单项添加了函数体为空的命令消息处理函数OnComputerTriangle。执行CompArea工程,可以测试“三角形面积”菜单命令。
【例11.2】为例11.1中的CompArea工程添加如图11.4所示的对话框资源,并进行对话框消息映射。
图11.4 计算三角形面积对话框
操作步骤为:
①打开例11.1中的CompArea工程文件。操作方法参见例10.3。
②在CompArea工程的工作区中选择ResourceView标签,在Dialog条目上单击鼠标右键,在弹出的快捷菜单中选择“Insert Dialog”菜单命令。
③这时在Dialog条目下会增加一个标识号为IDD_DIALOG1的条目,同时在客户区显示该对话框资源,如图11.5所示。
说明:如果在CompArea resources条目后出现一个*号,表明当前资源还未保存,最好要及时保存。
图11.5 新建对话框资源
④在对话框资源上单击鼠标右键,在弹出的菜单中选择“Properties”菜单命令,弹出Dialog Properties对话框,如图11.6所示。
图11.6 设置对话框属性
⑤将对话框资源的ID设置为“IDD_AREA”,Caption设置为“计算三角形面积”。关闭Dialog Properties对话框。
⑥选中Ok和Cancel按钮,按键盘上的Delete键完成删除,再为对话框添加如表11.1所示的控件,并设置相应属性。
表11.1 对话框控件属性
具体方法为:在Control 工具栏中选择控件类型,用鼠标左键拖至对话框中适当位置后松开鼠标(或者用鼠标左键选中后再在对话框中单击)。然后在控件上用鼠标右击打开属性对话框,按照表11.1设置相应属性。最后,利用Dialog 工具栏对各个控件进行如图11.7所示的布局。
图11.7 对话框资源
注意:对IDC_AREA 编辑框,还要在属性对话框的Style 标签中选中“Read-only ”检查框,使其不可编辑。可使用Dialog 工具栏最左边的Test 按钮测试对话框效果。(如果看不到所需工具栏,可在菜单栏和工具栏的空白处右击鼠标,在弹出的快捷菜单中进行选择。)
将所需控件在对话框中添加完成后,也即资源创建完毕。此时需要创建一个CDialog 类的派生类与该资源关联,下面的步骤7到步骤9完成此项工作。
⑦ 在对话框资源上双击鼠标左键(或者单击鼠标右键,在弹出的菜单中选择ClassWizard …菜单项,或者选择View|ClassWizard …菜单项),会弹出MFC ClassWizard 对话框,并紧接着弹出Adding a Class 对话框,如图11.8所示。
图11.8 Adding a Class对话框
⑧在Adding a Class对话框确认默认选项Create a new class,单击OK按钮,弹
出New Class对话框,如图11.9所示。
图11.9 New class对话框
⑨在Name编辑框中输入“CMyDlg”,其余设置取默认值,单击OK按钮。此
时自动生成该类的头文件和源文件分别为“MyDlg.h”和“MyDlg.cpp”。
⑩此时在MFC ClassWizard对话框的Projects项和Class name项中默认值都为
CMyDlg。选择Member Variables标签,在Control IDs列表框中选中IDC_SIDE1,单
击Add Variable…按钮,弹出Add Member Variable对话框,如图11.10所示。
图11.10 Add Member Variable对话框
?为IDC_SIDE1控件设置成员变量名为m_fSide1,在Category组合框中选择“Value”类型,在Variable type组合框中选择“float”数据类型,单击OK按钮。此时会在Member Variables标签下部出现对该成员变量设置取值范围,当用户进行输入数据时系统会自动进行数据的有效性验证,若不满足条件会进行提示。
?同样方法按照表11.2为其余编辑框控件设置相应的成员变量。
表11.2 编辑框控件的成员变量属性
此时,系统自动在CMyDlg类的构造函数中对这4个成员变量进行初始化,初始化数值均为0.0。
?选择Message Maps标签,为两个按钮添加消息处理函数。在Object IDs列表框中选中“IDC_TRIANGLE_AREA”,在Messages列表框中选中“BN_CLICKED”,
单击“Add Function…”按钮,弹出Add Member Function对话框,如图11.11所示。
图11.11 为“计算”按钮添加消息处理函数
?使用默认成员函数名OnTriangleArea,单击OK按钮。
?在Object IDs列表框中选择“IDC_RESET”,以同样方法为“重置”按钮添加消息处理函数OnReset。单击OK按钮关闭MFC ClassWizard对话框。
?在工作区选择ClassView标签,展开CMyDlg类,双击“OnTriangleArea ()”,编译器自动在客户区打开MyDlg.cpp文件,并且定位到CMyDlg:: OnTriangleArea ()函数的开头处。在该函数中增加以下代码:
void CMyDlg::OnTriangleArea()
{ //TODO: Add your control notification handler code here UpdateData();
if(m_fSide1+m_fSide2>m_fSide3 && m_fSide1+m_fSide3>m_fSide2
&& m_fSide3+m_fSide2>m_fSide1) //判断能否构成三角形
{
float s = (m_fSide1 + m_fSide2 + m_fSide3)/2;
m_dArea = sqrt(s * (s-m_fSide1) * (s-m_fSide2) * (s-m_fSide3)); //计算三角形面积
CString str;
str.Format("%.2f", m_dArea); //保留两位小数
m_dArea = atof(str); //使用atof函数将字符串转换为符点数
UpdateData(FALSE); //更新对话框中的数据
}
else
{
AfxMessageBox("无法构成三角形,请重新输入!");
}
}
?以同样方法为CMyDlg::OnReset()函数增加代码如下:
void CMyDlg::OnReset()
{ //TODO: Add your control notification handler code here m_fSide1 = 0;
m_fSide2 = 0;
m_fSide3 = 0;
m_dArea = 0;
UpdateData(FALSE); //更新对话框中的数据
}
?在MyDlg.cpp文件开头部分添加下面的包含语句:
#include
?执行CompArea工程,测试程序运行效果。
至此,与对话框资源相关的类及成员已经创建完成,下面就可以通过该对话框类的对象显示和使用对话框了。
11.1.2对话框的使用
对话框分为模式对话框和无模式对话框两种。从用户的观点看,模式对话框显示时,用户不能在同一个应用程序的其他地方做其他操作,直到该对话框关闭。通常使用的对话框大部分是模式对话框,例如文件“打开/另存为”对话框;无模式对话框显示时,用户可以操作其他界面对象,例如主窗口、菜单、工具栏等,以及常用的Word 应用程序中的“查找和替换”对话框、“符号”对话框等都是无模式对话框。当需要创建一个对话框时,必须确定该对话框是模式对话框还是无模式对话框,二者的显示方法是不同的。
在程序中创建对话框对象后,可以调用DoModal函数或ShowWindow函数显示对话框。而在对话框显示之前,系统会调用虚函数CDialog:: OnInitDialog对对话框进行初始化。因此,这个函数通常会在派生类中被扩充继承,用户可以加入一些自己的初始化工作。在CDialog:: OnInitDialog函数中会执行CWnd::UpdateData(FALSE)函数,完成用对话框成员变量的值去初始化对话框。当用户向对话框控件输入数据后,必须调用UpdateData()函数将控件中的数据传递给相应的成员变量。
(1)模式对话框
模式对话框是最常使用的对话框。当模式对话框打开时,将建立自己的消息循环,使得用户只能与该对话框进行交互,其他的用户界面对象接收不到输入信息,也不会做出任何响应。
模式对话框的显示是通过调用CDialog::DoModal函数实现的,当对话框关闭后该函数才返回,该函数原型为:
virtual int DoModal ();
返回值为IDOK时表示用户单击了OK按钮,此时系统先调用该按钮消息处理函数OnOK,然后DoModal函数才返回;返回值为IDCANCEL时表示用户单击了对话框窗口的关闭按钮或者Cancel按钮,此时系统先调用该按钮消息处理函数OnCancel,然后DoModal函数才返回。
通常有两种对话框对象创建方式:一种是在视图类头文件中创建为成员变量。另一种是在视图类的成员函数中临时创建。
【例11.3】为例11.2的CompArea工程的菜单命令“计算|三角形面积”添加处理代码,使例11.2中创建的对话框作为模式对话框进行显示,获取用户输入的三个边长并计算三角形面积后输出。
操作步骤为:
①在工作区选择ClassView标签,展开CCompAreaView类,双击成员函数OnComputerTriangle(),编译器自动在客户区打开“CompAreaView.cpp”文件,并定位到CCompAreaView::OnComputerTriangle()函数开头处。
②为OnComputerTriangle()函数添加代码如下:
void CCompAreaView::OnComputerTriangle()
{ //TODO: Add your command handler code here
CMyDialog mydlg; //创建对话框对象
mydlg.DoModal(); //显示模式对话框
}
③在CompAreaView.cpp文件开头部分添加下面的包含语句:
#include "MyDlg.h"
④编译,链接和运行程序,测试“计算|三角形面积”菜单项功能及模式对话框的效果。如图11.12所示。
图11.12 CompArea工程执行结果
这个例子中,对话框对象mydlg的生存周期仅限于成员函数CCompAreaView::OnComputerTriangle中。当该函数结束时,系统将自动调用CMyDlg
类的析构函数删除mydlg对象。
(2)无模式对话框
当无模式对话框打开时,将和应用程序共用一个消息循环,此时用户既可以和该对话框进行交互,也可以选择其它用户界面后和其他对象进行交互。无模式对话框需要调用CDialog::Create函数动态创建,如果对话框资源具有Visiable风格,则对话框可立即显示出来,否则需要调用CWnd::ShowWindow(SW_SHOW)函数来显示该对话框,当对话框显示后Create函数立即返回。
在CDialog类定义中,Create函数原型为:
BOOL Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);
参数:
?lpszTemplateName为以NULL结束的字符串,表示对话框资源名。
?nIDTemplate为对话框资源ID号。
?pParentWnd为指向对话框所属父窗口对象指针,缺省值为NULL,表示对话框对象的父窗口设置为主程序窗口。
返回值:若对话框创建和初始化成功,则返回非0值,否则返回0。
【例11.4】为例11.3中的CompArea工程添加一个无模式对话框类型的输出信息对话框,如图11.13所示,当用户在计算三角形面积时用来显示每次的计算信息。
图11.13 输出信息对话框
操作步骤:
①在Visual C++中打开“CompArea.dsw”文件,使用对话框资源编辑器添加对话框资源(方法同例11.2的步骤2至步骤4),设置ID为“IDD_OUTPUTINFO”,设置Caption为“输出信息”。
②删除OK按钮和Cancel按钮。
③添加一个列表框控件,ID为“IDC_INFOLIST”,在属性对话框的Style标签中选择Horizontal scroll、V ertical scroll,不选Sort,其余使用默认设置。
④在对话框资源上双击鼠标左键(或者单击鼠标右键,在弹出的菜单中选择ClassWizard…),会弹出MFC ClassWizard对话框,并紧接着弹出Adding a Class对话框,如图11.8所示。
⑤在Adding a Class对话框确认默认选项Create a new class,单击OK按钮,弹
出New Class对话框,如图11.14所示。在Name编辑框中输入“CInfoDialog”,基类为CDialog,其余设置取默认值,单击OK按钮。系统自动生成头文件和源文件为“InfoDialog.h”和“InfoDialog.cpp”。
图11.14 New class对话框
⑥在MFC ClassWizard对话框中,选择Member Variables标签,为对话框中的列表框控件在CInfoDialog类中添加相关联的成员变量m_OutputInfo,在Category组合框中选择“Control”类型,在Variable type组合框中选择“CListBox”类型,如图11.15所示。
图11.15 添加ListBox控件成员变量
⑦单击Add Member Variable对话框的OK按钮,再单击MFC ClassWizard对话框的OK按钮。
当用户在“计算三角形面积”对话框中单击“计算”按钮时,应该显示“输出信
息”对话框,并在列表框中显示计算信息。因此需要在“计算”按钮的消息处理函数CMyDlg::OnTriangleArea()中添加代码实现具体功能。
⑧在工作区中选择ClassView标签,在CMyDlg条目上双击打开“MyDlg.h”文件,在开头部分添加包含语句:
#include "InfoDialog.h"
在类的定义中添加成员变量:
public:
CInfoDialog * m_pInfodlg; //定义输出信息对话框对象指针
⑨展开CMyDlg类,双击构造函数,编译器自动在客户区打开“MyDlg.cpp”文件,并定位到CMyDlg::CMyDlg()函数开头处。添加代码如下:
m_pInfodlg = NULL; //初始化输出信息对话框对象指针
⑩编辑析构函数CMyDlg::~CMyDlg(),添加代码如下:
CMyDialog::~CMyDialog()
{
if(m_pInfodlg != NULL)
{
delete m_pInfodlg; //释放输出信息对话框对象指针
}
}
?编辑CMyDlg::OnTriangleArea()函数,添加代码如下:
void CMyDlg::OnTriangleArea()
{ //TODO: Add your control notification handler code here if(m_pInfodlg == NULL)
{
m_pInfodlg = new CInfoDialog; //使用new运算符申请对话框对象
m_pInfodlg->Create(IDD_OUTPUTINFO, NULL); //创建无模式对话框}
m_pInfodlg->ShowWindow(SW_SHOW); //显示无模式对话框
//设置列表框水平滚动宽度为1000像素
m_pInfodlg->m_OutputInfo.SetHorizontalExtent(1000);
UpdateData(TRUE); //将控件中的数据传递给相应的变量
if(m_fSide1+m_fSide2>m_fSide3 && m_fSide1+m_fSide3>m_fSide2 && m_fSide3+m_fSide2>m_fSide1) //判断能否构成三角形
{
float s = (m_fSide1 + m_fSide2 + m_fSide3)/2;
m_dArea = sqrt(s * (s-m_fSide1) * (s-m_fSide2) * (s-m_fSide3)); //计算三角形面积
CString temp;
temp.Format("%.2f", m_dArea); //保留两位小数
m_dArea = atof(temp); //使用atof函数将字符串转换为符点数
UpdateData(FALSE); //在控件中显示计算结果
CString strInfo;
strInfo.Format("第一条边:%f, 第二条边:%f,第三条边:%f, 面积:%f", m_fSide1, m_fSide2, m_fSide3, m_dArea); //格式化计算信息
//向模式对话框中添加计算信息
m_pInfodlg->m_OutputInfo.AddString(strInfo);
}
else
{
m_pInfodlg->m_OutputInfo.AddString("无法构成三角形,重输");
}
}
?编译,链接和运行程序,测试菜单“计算|三角形面积”的功能及无模式对话框的运行效果。一次运行的测试情况如图11.16所示。
图11.16 CompArea工程执行结果
11.1.3对话框的销毁
当向工程中插入对话框资源时,会默认包含一个OK按钮和一个Cancel按钮。当为该对话框资源创建新类时通常会从基类CDialog派生。在CDialog类定义中有:protected:
virtual void OnOK();
virtual void OnCancel();
当单击OK按钮关闭对话框时,系统会执行CDialog::OnOK函数。当单击Cancel 按钮或对话框关闭按钮时,系统会执行CDialog::OnCancel函数。如果用户在对话框派生类中对这两个函数进行了重载,则先调用派生类中的OnOK函数(或者OnCancel 函数),再调用基类CDialog中的OnOK函数(或者OnCancel函数)。
这两个函数的定义如下:
void CDialog::OnOK()
{
if (!UpdateData(TRUE))
{
TRACE0("UpdateData failed during dialog termination.\n");
//the UpdateData routine will set focus to correct item
return;
}
EndDialog(IDOK);
}
void CDialog::OnCancel()
{
EndDialog(IDCANCEL);
}
显然这两个函数都是调用EndDialog函数来关闭对话框,在CDialog类中EndDialog 函数原型为:
void EndDialog(int nResult);
当单击OK按钮关闭对话框时,参数nResult值为IDOK,当单击Cancel按钮或对话框关闭按钮来关闭对话框时,参数nResult值为IDCANCEL。实际上,EndDialog函数不会立即关闭对话框,它只是设置一个标志,指示当前函数处理结束后立即关闭对话框。
(1)模式对话框的销毁
模式对话框的显示是通过调用DoModal函数实现的,当对话框关闭后该函数才返回。当用户关闭对话框后模式对话框就已经被销毁了,但只要对话框对象还存在,还可以使用DoModal来创建一个新的模式对话框。若对话框对象是在视图类的成员函数中临时创建,则当该函数执行结束时,模式对话框的析构函数将被调用。若对话框对象是在视图类头文件中创建为成员变量,则当视图关闭时先调用视图类的析构函数,再调用模式对话框类的析构函数。
(2)无模式对话框的销毁
无模式对话框通常由父视图或框架窗口(应用程序的主框架窗口或文档框架窗口)创建和拥有。当无模式对话框指针作为父窗口类成员变量时,如果用户关闭无模式对
话框时,对话框并没有被销毁,此时只要无模式对话框指针还存在,还可以调用ShowWindow函数来显示该对话框。当无模式对话框的父窗口关闭时,系统会自动调用父窗口的析构函数,因此必须在该析构函数中使用delete运算符释放无模式对话框指针(参见例11.4步骤10中的语句delete m_pInfodlg;)。
当在主窗口命令消息处理函数中动态创建局部无模式对话框指针时,显然不能在该函数结束时使用delete运算符释放无模式对话框指针。因为此时若释放无模式对话框指针则对话框窗口同时被销毁。在这种情况下,可以在模式对话框关闭时销毁自己,具体方法为:首先,在模式对话框类中,对OnCancel函数进行重载,调用DestroyWindow()强制销毁窗口。然后,使用ClassWizard工具,在模式对话框类中映射WM_DESTROY消息,在消息处理函数中使用语句delete this删除自身对象(参见例11.5的步骤15)。
【例11.5】为CompArea工程添加一个无模式对话框,用来显示当前日期和星期,如图11.17所示,测试无模式对话框的创建和销毁。
图11.17 当前日期对话框
操作步骤为:
①在Visual C++中打开“CompArea.dsw”文件。
②使用对话框资源编辑器添加对话框资源。在对话框上用鼠标右击,在弹出的快捷菜单中选择“Properties”菜单项打开Dialog Properties对话框,设置ID为“IDD_SHOWDATE”,设置Caption为“当前日期”。
③删除OK按钮和Cancel按钮。
④添加一个编辑框控件,ID为“IDC_DATE”,在属性对话框的Style标签中选择Read-only,其余使用默认设置。
⑤创建该对话框资源的对话框类CShowDate,基类为CDialog(方法同例11.2的步骤6)。系统自动生成头文件“ShowDate.h”和源文件“ShowDate.cpp”。
⑥在MFC ClassWizard对话框中,选择Member Variables标签,为CShowDate 类添加编辑框控件成员变量,变量名为m_strDate,在Category组合框中选择“Value”类型,在Variable type组合框中选择“CString”类型。
⑦在工作区中选择ResourceView,展开Menu项,双击IDR_MAINFRAME,使用菜单资源编辑器添加菜单“当前日期”,如图11.18所示。
图11.18 添加菜单“当前日期”
⑧在MFC ClassWizard中,为CCompAreaView类添加菜单IDD_SHOWDATE 的消息处理函数,如图11.19所示。
图11.19 添加菜单消息处理函数
⑨单击Add Member Variable对话框的OK按钮,再单击MFC ClassWizard对话框的OK按钮。
⑩在工作区中选择ClassView标签,展开CCompAreaView类,双击OnShowdate 函数,编译器自动在客户区打开“CompAreaView.cpp”文件,并定位到CCompAreaView::OnShowdate()函数开头处。添加代码如下:
void CCompAreaView::OnShowdate()
{
//TODO: Add your command handler code here
CShowDate *pShowdate;
pShowdate = new CShowDate; //使用new运算符创建显示日期对话框对象
if(NULL == pShowdate) //创建对话框对象失败
{
AfxMessageBox("Failed.");
return;
}
else //创建对话框对象成功
{
pShowdate->Create(IDD_SHOWDATE); //创建无模式对话框
pShowdate->ShowWindow(SW_SHOW); //显示无模式对话框
}
CTime time; //创建CTime类对象
time = CTime::GetCurrentTime(); //获取当前日期
CString str = time.Format("%Y-%m-%d-%A"); //格式化日期
pShowdate->m_strDate = str;
pShowdate->UpdateData(FALSE); //更新显示日期对话框}
?在“CompAreaView.cpp”文件开头部分添加包含语句:
#include "ShowDate.h"
?打开ShowDate.h文件,在CShowDate类定义中声明虚函数:
void OnCancel();
?打开ShowDate.cpp文件,添加函数定义:
void CShowDate::OnCancel() //重载OnCancel函数
{
DestroyWindow(); //销毁窗口
}
?打开MFC ClassWizard对话框,为CShowDate类添加WM_DESTROY消息的响应函数OnDestroy,如图11.20所示。
图11.20 向CShowDate类添加消息响应函数
?在Member functions列表框中双击OnDestroy条目,编译器在客户区自动打开
“ShowDate.cpp”文件,并定位到OnDestroy函数开头处,添加代码如下:void CShowDate::OnDestroy()
{
CDialog::OnDestroy();
delete this;
}
?编译,链接和运行程序,测试菜单“当前日期”的功能及无模式对话框的运行效果。
在创建该无模式对话框时,默认父窗口为应用程序主窗口,所以当打开无模式对话框后,既可使用模式对话框的关闭按钮进行关闭,也可在关闭应用程序主窗口的同时进行关闭。当单击主窗口关闭按钮时,系统要关闭所有文档,销毁所有窗口,退出程序,因此会向无模式对话框窗口发送WM_DESTROY消息,执行delete this;语句强行删除无模式对话框对象,从而销毁对话框窗口。
11.1.4对话框数据交换和验证机制
在上面的例子中,存在两个很重要的过程,一个是用户向对话框的编辑框控件输入数据后由按钮消息处理函数处理数据,另一个是处理后的数据显示到对话框的编辑框控件中。即在对话框控件和对话框类的成员变量之间存在着一个数据交换的过程。那么,这个过程是如何实现的呢?
1. CDataExchange类
对话框数据交换(Dialog Data Exchange,简称DDX)和对话框数据验证(Dialog Data Validation,简称DDV)是Visual C++用来实现对话框操作的重要机制。MFC为了简化这些操作,提供了CDataExchange类来支持对话框的数据交换和验证过程。CDataExchange类没有基类。
(1)成员变量
public:
BOOL m_bSaveAndValidate;
CWnd* m_pDlgWnd;
当m_bSaveAndValidate 值为TRUE 时,表示将数据从对话框控件传递到对话框类成员变量;反之,则表示将数据从成员变量传递到对话框控件。m_pDlgWnd通常为指向包含控件的对话框的指针。
(2)主要成员函数
1)构造函数
CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);
?参数pDlgWnd为包含控件的对话框的指针。
?参数bSaveAndValidate值为布尔值,为DDX和DDV设置方向。
2)HWND PrepareCtrl(int nIDC) 函数
?功能:框架调用这个成员函数为DDX和DDV准备指定控件。
?参数nIDC为非编辑控件ID。
?返回值:为所有非编辑控件的窗口句柄,类型为HWND,
3)HWND PrepareEditCtrl(int nIDC) 函数
?功能:框架调用这个成员函数为DDX和DDV准备指定编辑控件。
?参数nIDC为编辑控件的ID。
?返回值:为编辑控件的窗口句柄,类型为HWND。
2. 对话框数据交换和验证机制的实现过程
以例11.3为例,对话框数据交换和验证机制的实现包括如下过程:
(1)当新建对话框类CDialog的派生类CMyDlg时,系统在CMyDlg类中对虚函数CWnd::DoDataExchange进行了重载。代码如下所示:
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
说明:
ClassWizard工具将在此实现对话框数据交换和验证机制。注释中的
//{{AFX_DATA_MAP(CMyDlg) 和//}}AFX_DATA_MAP表示在此之间的代码是由系统自动生成,用来进行数据映射。程序中其它在//{{AFX_...和//}}AFX_...之间的代码同此理,用户不必修改。
(2)当在MFC ClassWizard对话框中为对话框中的控件添加成员变量并设置变量的取值范围后(如图11.21所示),系统会在类的定义中声明成员变量,并在构造函数中用默认值对成员变量进行初始化。
《面向对象程序设计C++》期末考试试卷(B) 一、单项选择题(每小题2分,共40分) 1、关于C++与C语言关系的描述中,()是错误的。 A.C语言是C++语言的一个子集B.C语言与C++语言是兼容的 C.C++语言对C语言进行了一些改进D.C++语言和C语言都是面向对象的 2、已知:int m=10; 下列表示引用的方法中,()是正确的。 A.int &x=m; B.int &y=10; C.int &z; D.float &t=&m; 3、考虑下面的函数原型声明:void testDefaulParam(int a,int b=7,char z='*'); 下面函数调用中,不合法的是()。 A.testDefaulParam(5); B.testDefaulParam(5,8); C.testDefaulParam(5,'#'); D.testDefaulParam(0,0,'*'); 4、系统在调用重载函数时往往根据一些条件确定哪个重载函数被调用,在下列选项中,不能作为依据的是()。 A.函数的返回值类型B.参数的类型C.函数名称D.参数个数 5、下列有关C++类的说法中,不正确的是()。 A.类是一种用户自定义的数据类型 B.只有类中的成员函数或类的友元函数才能存取类中的私有成员 C.在类中,如果不做特别说明,所有成员的访问权限均为私有的 D.在类中,如果不做特别说明,所有成员的访问权限均为公用的 6、已知X类,则当程序执行到语句X array[3];时,调用了()次构造函数。 A.0 B.1 C.2 D.3 7、有关析构函数的说法,不正确的是()。 A.析构函数有且仅有一个 B.析构函数和构造函数一样可以有形参 C.析构函数的功能是在系统释放对象之前作一些内存清理工作 D.析构函数无任何函数类型
一、填空题(每空1分,共14分) 1、观看以下程序: class point{ public: void show() {cout<<”point”< (A)指针(B)引用(C)枚举(D)结构 3、类成员的访问权限中,()只能被本类的成员函数和其友元函数访问。 (A)share (B)public (C)private (D)protected 4、关于构造函数,下列说法不正确的是()。 (A)构造函数名字和类名相同 (B)构造函数在创建对象时自动执行 (C)构造函数无任何函数返回类型 (D)构造函数有且只有一个 5、派生类可以访问其基类的()。 (A)公有成员(B)保护成员 (C)私有派生(D)公有和保护成员 6、下列关于运算符重载的描述中,错误的是()。 (A)运算符重载不可以改变操作数的个数 (B)运算符重载不可以改变运算符的功能 (C)运算符重载不可以改变结合方向 (D)运算符重载不可以改变运算优先级 7、C++语言是从早期的C语言逐渐发展演变而来的.与C语言相比,它在求解问题方法上进行的最大改进是() (A)面向过程(B)面向对象(C)安全性(D)复用性 8、对于类中定义的成员,其隐含访问权限为()。 A.public B.protected C.private D.static 9、下面有关重载函数的说法中正确的是() (A)重载函数必须具有不同的返回值类型;(B)重载函数形参个数必须不同; (C)重载函数必须有不同的形参列表(D)重载函数名可以不同; 10、有如下的对类“CSample”的说明,其中()是错误的。 class CSample { A.int a=23; B.CSample(); public: C.CSample(int val); D.~ CSample(); 11、在int a=3,int *p=&a;中,*p的值是( ) A.变量a的地址值 B.无意义 C.变量p的地址值 D.3 12、每个类()构造函数。 (A)只能有一个(B)只可有公有的 1 什么是面向对象程序设计,它与传统的结构式程序有什么不同。 面向对象程序设计是一种适用于设计、开发各类软件的范型。它是将软件看成是一个由对象组成的社会:这些对象具有足够的智能,能理解从其他对象接受的信息,并以适当的行为作出响应;允许低层对象从高层对象继承属性和行为。通过这样的设计思想和方法,将所模拟的现实世界中的事物直接映射到软件系统的解空间。 与传统的结构式程序设计相比,面向对象程序设计吸取了结构式程序设计的一切优点(自顶向下、逐步求精的设计原则)。而二者之间的最大差别表现在: ·面向对象程序采用数据抽象和信息隐藏技术使组成类的数据和操作是不可分割的,避免了结构式程序由于数据和过程分离引起的弊病。 · 面向对象程序是由类定义、对象(类实例)和对象之间的动态联系组成的。而结构式程序是由结构化的数据、过程的定义以及调用过程处理相应的数据组成的 2 用面向对象方法建立模型的思维过程是怎样的。 用面向对象方法建立拟建系统的模型的过程就是从被模拟现实世界的感性具体中抽象要解决的问题概念的过程。这种抽象过程分为知性思维和具体思维两个阶段,其中:·知性思维是从感性材料中分解对象,抽象出一般规定,形成了对对象的普遍认识。·具体思维是从知性思维得到出的一般规定中揭示的事物的深刻本质和规律,其目的是把握具体对象的多样性的统一和不同规定的综合。 3 解释以下概念: ①对象:在现实世界中,对象就是可以感觉到的实体。每个对象具有一个特定的名字以 区别于其他对象;具有一组状态用来描述它的某些特性;具有一组操作,每一个操作决定对象的一种功能或行为(为自身服务的操作和为其他对象提供服务的操作)。而在面向对象系统中,对象是可以标识的存储区域。每个对象的状态被保存在此区域中,而实现一类对象行为的操作(代码)被保存在另外相关的存储器区域中。 ②消息:消息是要求某个对象执行其某种功能操作(方法)的规格说明。因此,消息是 由消息的接收者、消息要求提供的操作(消息名)和必要的参数组成的。 ③类:在现实世界中,类是对一组具有共同特性(属性和行为)的客观对象的抽象。而 在面向对象系统中,类是由程序员自定义的具有特定结构和功能的类型,是一种代码共享的手段。 ④实例:任何一个对象都是该对象所属类的一个具体实例。 ⑤公有消息:是由对象外向对象发送的消息,用于激活该对象的某种方法。 ⑥私有消息:是由对象向自身发送的消息,用于内部操作;该类消息不能从对象外向该 对象发送。 ⑦消息序列:在面向对象系统中一个事件的发生总会有多个对象的多次相互作用才能完 成,使得这些对象能够相互作用的消息组成的序列被称为消息序列。 4 类与实例的关系如何? 类是创建对象的模板,而对象是实现类的实例。属于同一类的不同实例必须具有: ·相同的操作集合; ·相同的静态属性集合; ·不同的对象名和属性动态值。 西安石油大学 2017 本科专业人才培养方案 专业名称测控技术与仪器 专业代码080301 院(部、系) 名称电子工程学院 测控技术与仪器 Measuring & Control Technology and Instrument 专业代码:080301 一、培养目标 本专业培养具备基本理论、知识和应用能力,能够在石油及相关领域从事测控仪器装备设计开发、制造、技术服务和经营管理等工作,具有创新意识的高素质复合型工程技术人才。毕业后经过五年左右的工程实践,具备: 1、综合运用多学科知识进行测量、分析、控制和解决石油及相关领域测控工程问题的能力,完成测控仪器装备的设计开发、制造和技术服务; 2、良好人文素养、社会责任感和工程伦理道德; 3、在职场中能以个人、成员或领导的角色,恪尽职守、交流合作或协调组织,有效发挥自身和团队作用; 4、创新意识和自主学习能力,以适应职业或行业发展需求。 二、毕业要求 以下毕业要求中的复杂工程问题均指石油及相关测控领域中的复杂工程问题。 1. 工程知识:具备数学、自然科学、工程基础、专业基础和专业知识,并能够应用于解决复杂工程问题。 2. 问题分析:能够应用数学、自然科学和工程科学的基本原理,识别、表达、并通过文献研究分析复杂工程问题,以获得有效结论。 3.设计/开发解决方案:能够设计针对复杂工程问题的解决方案,设计满足特定需求的系统、单元(子系统),并能够在系统设计环节中体现创新意识,考虑社会、健康、安全、法律、文化以及环境等因素。 4. 研究:能够基于科学原理并采用科学方法对复杂工程问题进行研究,包括设计实验、分析与解释数据、并通过信息综合得到合理有效的结论。 5. 使用现代工具:能够针对复杂工程问题,开发、选择与使用恰当的技术、资源、现代工程工具和信息技术工具,包括对复杂工程问题的预测与模拟,并能够理解其局限性。 6.工程与社会:能够基于石油测控及相关领域的背景知识进行合理分析,评价专业工程实践和复杂工程问题解决方案对社会、健康、安全、法律以及文化的影响,并理解应承担的责任。 7.环境和可持续发展:理解环境保护和社会可持续发展的内涵和意义,能够考虑和评价石油项目对环境保护、社会可持续发展的影响。 8. 职业规范:具有人文社会科学素养、社会责任感,能够在工程实践中理解并遵守石油及其相关什么是面向对象程序设计
西安石油大学
《面向对象程序设计》答案