实验6对话框.docx
《实验6对话框.docx》由会员分享,可在线阅读,更多相关《实验6对话框.docx(17页珍藏版)》请在冰豆网上搜索。
实验6对话框
实验6对话框
实验目的
1、掌握对话框和CDialog类
2、掌握对话框的创建、显示和数据校验机制
3、掌握模式对话框与无模式对话框的使用方法
4、掌握公共对话框的使用
实验内容
本节主要掌握对话框的基本知识和使用方法。
对话框的基本知识包括对话框模板的设计,模板与对话框类的连接,对话框的消息循环。
同时还对颜色对话框、字体对话框和文件对话框等常用的公共对话框进行了解。
例1.设计画笔宽度选择对话框,通过该对话框可以调整画笔的宽度,范围为1~10,并使用该画笔在客户区画一个圆。
对话框资源创建的步骤如下:
(1)利用AppWizard创建一个基于MFC的单文档应用程序ex71。
(2)单击工作区中的ResourceView,选中Dialog,右击Dialog,在弹出的菜单中选择InsertDialog,这时,在Dialog目录下新增了一个标识为IDD_DIALOG1的条目,即添加了一个新对话框资源,同时在对话框编辑器中显示出该对话框资源。
新建的对话框具有两个默认的按钮控件即OK和Cancel,如下图。
在对话框编辑器中,右击该对话框,在弹出的菜单中选择属性,弹出对话属性对话框,用来设计对话框的属性。
在General选项卡中设置对话框的ID为IDD_PenDlg,对话框的标题为“画笔宽度选择”,如下图。
(3)向对话框中添加控件。
1)一个静态文本控件。
在对话框编辑器中,选中控件窗口中的静态文本,拖动到对话框中,右键单击已添加的静态文本控件,在弹出的菜单中选择属性,弹出该控件属性页,设计该控件的标题为“画笔宽度”。
2)一个编辑框控件。
用同样的方法添加编辑框控件,并在其属性页中,设计编辑框的ID为IDC_Width。
3)一个微调控件。
在微调控件的属性页里,General标签也中设置微调控件(Spin)的属性,ID为IDC_SPIN,Style标签页中的Alignmeng对齐方式选择为right;选中Setbuddyinteger。
最后移动对话框上面的OK和Cancel按钮的位置。
添加完控件后的对话框资源如下图。
(4)通过Dialog工具栏调整控件的位置。
此外,可以在对话框中用静态文本控件添加一些简要说明。
(5)单击Dialog工具栏中的Test按钮,测试新建对话框的效果。
(6)创建对话框类:
通过点击菜单查看->建立类向导弹出MFCClassWizard对话框并紧接着弹出AddingaClass对话框询问是否需要新建一个类,选取Createanewclass,确定后弹出新建类对话框。
(7)在新建类对话框中的Name编辑框中输入新建类名CPenDlg,其基类为CDialog,如下图,确定后,新建类已添加到工程中。
打开工作区的ClassView,可以看到新增加了一个类CPenDlg。
(8)为对话框控件添加变量和对象:
添加IDC_Width控件变量,在建立类向导对话框中选择MemberVariable,在Classname下拉列表中选择CPenDlg,为其添加控件变量和控件对象。
在ControlsIDs中选择IDC_Width,单击AddVariable按钮弹出对话框。
该控件变量名为m_nWidthEdit。
Category下拉列表框中选择Value,表示添加的是控件变量,(Control便是添加的是控件对象),Variabletype表示的是添加的变量或对象的类型,选择int。
单击OK按钮,界面返回到ClassWizard对话框,为该变量输入最小值1和最大值10。
如下图所示
(9)同理添加IDC_Width控件对象m_ctrlWidthEdit,Category下拉列表框中选择Control项;添加IDC_SPIN控件对象m_ctrlSpin,Category下拉列表框中选择Control项,Variabletype选择为CSpinButtonCtrl。
(10)对话框中控件的初始化。
A.在构造函数中主要对所定义的数据成员进行初始化,通常类向导可以产生它所需要的数据成员的初始化代码,用户不需要做这项工作。
构造CPenDlg类的函数代码如下:
CPenDlg:
:
CPenDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CPenDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CPenDlg)
m_nWidthEdit=0;
//}}AFX_DATA_INIT
}
(11)在OnInitDialog()函数中初始化。
在OnInitDialog()函数是WM_INITDIALOG消息的响应函数。
当对话框接受WM_INITDIALOG消息时,对话框框架及控件已经建立起来,但对话框中的控件还没显示出来。
这样就可在OnInitDialog()函数中设置对话框的外观、大小及其他相关内容。
本程序中,可在OnInitDialog()函数中为微调控件设计伙伴及范围。
用类向导为对话框添加WM_INITDIALOG消息响应函数OnInitDialog():
BOOLCPenDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
m_ctrlSpin.SetBuddy(&m_ctrlWidthEdit);
m_ctrlSpin.SetRange(1,10);
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
//EXCEPTION:
OCXPropertyPagesshouldreturnFALSE
}
(12)在应用程序中显示对话框。
在应用程序工具栏中,添加新按钮“画”,表示画笔选择,在属性页中设置其ID为ID_TESTDLG,Prompt为“调用画笔选择对话框\n画笔选择”。
利用类向导,为ID_TESTDLG在CEx71view类中添加WM_COMMAND消息映射函数OnTestdlg(),代码如下:
voidCEx71View:
:
OnTestdlg()//需在此文件开始处引用头文件”PenDlg.h”
{
CPenDlgdlg;
dlg.DoModal();
}
(13)编译、链接并运行程序,单击工具栏的按钮“画”后出现新建的对话框。
但是,对话框目前还不能完成设置画笔宽度的功能,因为还没有创建相应的数据传递和绘图函数。
对话框数据交换(DDX)机制用于初始化对话框中的控件或从对话框中获得用户输入的数据;对话框的验证(DDV)用于验证对话框中数据输入的有效性。
为了使对话框的数据成员能够使用DDX/DDV,则必须使用ClassWizard创建成员变量,设置数据类型,并指定验证规则。
ClassWizard通过一套特殊的语法格式来自动维护DDX/DDV。
在例1中,新建对话框包含一个编辑框控件用于设置画笔宽度,和编辑控件相关联的有两个变量:
一个控件(Control)变量和一个值(Value)变量。
如果使用DDX机制,则一般在OnInitDialog()处理函数或对话框构造函数中设置成员变量的初始值。
当一个对话框显示之后,所有初始值被传递到控件中。
在添加成员变量时,单击OK按钮关闭类向导对话框,那么类向导自动地在构造函数中加入控件的初始化值。
对话框数据交换时在对话框类的DoDataExchange()函数中完成的。
该例程中,用类向导给对话框添加成员变量后DoDataExchange()函数的代码如下:
voidCPenDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPenDlg)
DDX_Control(pDX,IDC_SPIN,m_ctrlSpin);
DDX_Control(pDX,IDC_Width,m_ctrlWidthEdit);
DDX_Text(pDX,IDC_Width,m_nWidthEdit);
DDV_MinMaxInt(pDX,m_nWidthEdit,1,10);
//}}AFX_DATA_MAP
}
对话框数据验证(DDV)。
编译、运行ex71,单击工具栏中的“画”按钮,在出现的“画笔选择”对话框中,输入画笔宽度20,单击OK,观察DDV机制提示的出错信息。
修改上例,添加“画笔选择”菜单项,在该菜单项下,添加子菜单“模式对话框”和“无模式对话框”,其ID分别为ID_Modal和ID_NoModal,并分别为这两个子菜单项在CEx71View类中添加WM_COMMAND消息处理函数CEx71View:
:
OnModal()和CEx71View:
:
OnNoModal()。
这两个子菜单分别实现模式对话框和无模式对话框的调用。
对话框与视图间的数据传递:
1、首先,在视图类CEx71View中添加一个int型成员变量m_nWidth,用于实现与对话框成员变量m_nWidthEdit间的数据传递,并在CEx71View类的构造函数中将其初始化为1,即在构造函数中添加代码m_nWidth=1;修改CEx71View:
:
OnDraw()函数,代码如下
voidCEx71View:
:
OnDraw(CDC*pDC)
{
CEx71Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CPenpen;
pen.CreatePen(PS_SOLID,m_nWidth,RGB(255,0,0));
pDC->SelectObject(&pen);
pDC->Ellipse(100,100,300,300);
}
2、修改CEx71View:
:
OnModal()函数,代码如下:
voidCEx71View:
:
OnModal()
{
CPenDlgdlg;
dlg.m_nWidthEdit=m_nWidth;
if(dlg.DoModal()==IDOK)
{
m_nWidth=dlg.m_nWidthEdit;
Invalidate();
}
}
修改例7.1,增加一个ID为IDD_NPenDlg的新对话框资源如下图所示。
启动类向导,添加名称为CNPenDlg的新类。
设置Apply按钮的ID为IDC_Apply,并给其添加BN_CLICKED消息响应函数OnApply()。
同时,在CNPenDlg类中添加相应的控件变量如图(CNPenDlg类与CPenDlg类的控件使用相同的变量):
继续修改,为CNPenDlg类添加WM_INITDIALOG消息响应函数OnInitDialog(),其代码如下:
BOOLCNPenDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
m_ctrlSpin.SetBuddy(&m_ctrlWidthEdit);//将编辑框设置为微调控件的伙伴窗口。
m_ctrlSpin.SetRange(1,10);
returnTRUE;
}
在“无模式对话框”菜单项的响应函数CEx71View:
:
OnNoModal()中添加代码显示无模式对话框,方法如下:
先在CEx71View类中添加成员变量CNPenDlg*NpenDlg(其中,变量类型为CNPenDlg*,变量名为NpenDlg,访问权限为public)。
voidCEx71View:
:
OnNoModal()
{
NpenDlg=newCNPenDlg(this);
NpenDlg->m_nWidthEdit=m_nWidth;
NpenDlg->Create(CNPenDlg:
:
IDD);
NpenDlg->ShowWindow(SW_SHOW);
}
为无模式对话框类CNPenDlg中添加重载的OnOK()函数:
voidCNPenDlg:
:
OnOK()
{
UpdateData(TRUE);
CDialog:
:
OnOK();
}
注意:
需要在ex71View.h文件中添加语句classCNPenDlg;。
这是因为成员变量NpenDlg的定义放在头文件ex71View.h中,因此需要在该头文件开始处声明CNPenDlg类的定义。
编译、链接并运行程序,比较模式对话框和无模式对话框的不同点。
此时,无模式对话框的OK按钮和Apply按钮均不能起到改变画笔宽度的作用。
在CNPenDlg类的定义中增加一个CView类的指针CView*pView,重载一个构造函数CNPenDlg:
:
CNPenDlg(CView*pParent),构造函数将接受CEx71View的指针,并保存在pView中。
在NPenDlg.cpp中,添加CNPenDlg(CView*pParent)构造函数代码如下:
CNPenDlg:
:
CNPenDlg(CView*pParent)
{
pView=pParent;
}
为实现Apply按钮的功能,现在NpenDlg.h文件首部添加自定义消息:
#defineWM_APPLYWM_USER+1
然后利用类向导在CNPenDlg类中添加Apply按钮的消息处理函数OnApply(),实现向视图发送消息,代码如下:
voidCNPenDlg:
:
OnApply()
{
UpdateData(TRUE);
pView->PostMessage(WM_APPLY);
CDialog:
:
OnOK();
}
在视图中添加WM_APPLY消息的处理函数Apply()。
A.在Ex71View.h文件中添加WM_APPLY消息处理函数原型
afx_msgvoidApply(WPARAMwParam,LPARAMlParam);
B.在Ex71View.cpp中添加WM_APPLY消息的消息映射
ON_MESSAGE(WM_APPLY,Apply)
C.在Ex71View.cpp文件中添加Apply()函数的功能,代码如下:
voidCEx71View:
:
Apply(WPARAMwParam,LPARAMlParam)
{
m_nWidth=NpenDlg->m_nWidthEdit;//将对话框中m_nWidthEdit的值传给视图的m_nWidth;
Invalidate();//重绘图形
}
D.实现OK按钮的功能
当用户单击OK按钮时,在关闭对话框前也需要向视图发送消息,通知视图进行重绘图形,发送消息的功能与Apply按钮功能相同。
voidCNPenDlg:
:
OnOK()
{
UpdateData(TRUE);
pView->PostMessage(WM_APPLY);
CDialog:
:
OnOK();
}
编译、链接并运行程序,观察模式对话框与无模式对话框之间的区别。
例2.在应用程序中添加属性页对话框,并通过“对话框”菜单中的“属性页对话框”命令项进行显示。
步骤如下:
(14)利用AppWizard新建一个基于MFC【EXE】的单文档工程ex72.
(15)添加属性页对话框资源。
1、通过菜单命令工程->添加到工程->ComponentsandControls打开ComponentsandControlsGallery对话框。
2、在ComponentsandControlsGallery对话框中的目录列表中双击VisualC++Components条目,目录列表改变,拖动滚动条,找到PropertySheet项并选中。
3、单击Insert按钮,在弹出的MicrosoftVisualC++消息对话框中单击“确定”按钮后弹出PropertySheetWizard对话框。
4、在PropertySheetWizard对话框中选择所要添加的属性框类型。
默认的是一般类型的属性框,及选中的是PropertySheet,单击“下一步”。
5、在紧接着弹出的对话框中的Supportpreviewing复选框要求确认是否在属性框中添加预览功能,默认值为不添加预览功能。
下面的单选按钮时确认将属性框设置为模式还是无模式类型,默认值为模式,选中的是No。
保持默认值,单击“下一步”。
6、在接着弹出的对话框中要求选择在哪个类中对属性对话框进行操作。
通过ComboBox组合框控件,选中CEx72View。
单击“下一步”按钮。
7、在随后弹出的对话框中,要求确认属性框中的属性页个数,默认值为2,保持默认,单击“下一步”。
8、在接下来弹出的对话框中要求确认将要添加的CPropertySheet类和CPropertyPage类的派生类的名称。
可以通过单击按钮改变。
保留默认值,单击“完成”。
9、关闭ComponentsandControlsGallery对话框。
通过上述步骤,在程序中添加了如下一些内容:
●一个CPropertySheet类的派生类CMyPropertySheet。
●两个CPropertyPage类的派生类CMyPropertyPage1和CMyPropertyPage2。
●与CMyPropertyPage1来和CMyPropertyPage2类相关联的对话框资源。
●在CEx72View.cpp文件的头部添加了一条包含语句:
#include“MyPropertySheet.h”
在CEx72View类中添加了CEx72View:
:
OnProperties()函数。
内容如下:
VoidCEx72View:
:
OnProperties()
{
CMyPropertySheetpropSheet;
propSheet.DoModal();
}
(16)修改菜单资源,添加“对话框”菜单,并添加“属性页对话框”子菜单项。
其ID为ID_SheetDlg,Caption为属性对话框,在CEx72View中添加响应函数代码如下:
VoidCEx72View:
:
OnSheetDlg()
{
OnProperties();
}
编译、链接并运行程序,选中“对话框”菜单中的“属性页对话框”项,出现属性页对话框。
例2.设计“打开”和“保存”对话框,实现对文本文件的选择打开和保存。
(1)利用AppWizard生成基于MFC【EXE】的单文档应用程序ex73。
(2)添加文件对话框显示代码。
文件对话框的现实方法主要有两种:
一种是通过重载已经存在于MFC生成框架中的文件对话框;另一种方法是直接调用代码显示对话框。
1、利用ClassWizard重载“文件”菜单下的“打开”子菜单。
在ex73工程中,打开ClassWizard,选择MessageMaps页面,在ClassName编辑框中选择CEx73View,在ObjectIDs编辑框中选择ID_FILE_OPEN,在Messages编辑框中选择COMMAND,单击AddFunction按钮,采用系统产生的默认名称OnFileOpen。
然后,单击EditCode按钮,编辑该函数的实现代码。
如下:
VoidCEx73View:
:
OnFileOpen()
{
CStringfilter=”TXTFiles(*.txt)|*.txt||”;
CFileDialogmydialog(TRUE,0,0,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY,filter);
If(mydialog.DoModal()==IDOK){
CStringstr=mydialog.GetPathName();
MessageBox(str);}
}
2、在响应函数中添加调用代码,在工程ex73中,添加新的菜单“公共对话框”并在其下添加新的子菜单项“文件对话框”。
ID为ID_FileDlg,prompt为文件对话框。
相应的WM_COMMAND消息处理函数代码同上。
编译、运行程序,当单击“打开”或者“文件对话框”。
例3.通过字体对话框来选择所显示文本的字体和颜色。
步骤如下:
(1)利用AppWizard创建一个基于MFC的单文档应用程序ex74.
(2)在视窗中,用初始化的字体及颜色显示字符串“Hello,Fontdialogtest!
”。
首先在CEx74View类中定义两个成员变量:
LOGFONTfnt和COLORREFcrColor分别表示字体即颜色,并在CEx74View类的构造函数中对量变量进行初始化,代码如下:
CEx74View:
:
CEx74View()
{
crColor=RGB(255,0,0);//字体初始颜色红色,与圆的颜色相同
memset(&fnt,0,sizeof(LOGFONT));
strcpy(fnt.lfFaceName,"Arial");//初始字体名称
fnt.lfHeight=50;//字体初始高度
}
然后修改OnDraw函数,用所给字体及颜色来显示字符串。
代码如下:
voidCEx74View:
:
OnDraw(CDC*pDC)
{
CEx74Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
pDC->SetTextColor(crColor);/字体的颜色
CFontmyfont;
myfont.CreateFontIndirect(&fnt);//间接创建一字体
pDC->SelectObject(&myfont);
pDC->TextOut(100,100,"Hello,Fontdialogtest!
");
}
添加“字体选择”菜单项,其ID为ID_Font,并为该菜单项添加WM_COMMAND消息处理函数OnFont(),通过该函数可以显示字体对话框,并使选择的字体及颜色有效,代码如下:
voidCEx74View:
:
OnFont()
{
CFontDialogdlg(&fnt);//用构造函数初始化对话框中的字体
dlg.m_cf.rgbColors=crColor;//初始化对话框中的颜色
if(dlg.DoModal()==IDOK)
{
dlg.GetCurrentFont(&fnt);//获取所选字体
crColor=dlg.GetColor();//获取所选颜色
Invalidate();
}
}
例4.通过颜色对话框来改变在客户区所画圆的颜色。
(1)新建一个MFCAppWizard[exe]类型的单文档工程ex75。
(2)在ex75中,打开菜单资源编辑器编辑菜单,在File主菜单下增加新的菜单项“颜色对话框”,其ID实ID_COLORDIALOG。
(3)在CEx75View类中增加新的数据成员COLORREFcrColor,代表所画圆采用的颜色。
(4)在CEx75View类的OnDraw()函数中增加绘制椭圆的代码如下:
voidCEx75View:
:
OnDraw(CDC*pDC)
{
CEx75Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
CPenmypen;
mypen.CreatePen(PS_SOLID,3,crColor);
pDC->SelectOb