第七章、对话框(一)

7.1对话框基本知识

对话框就是一个窗口,可以接收消息、移动、关闭以及在它的客户区绘图。

7.1.1控件

所有的控件也是一个个窗口。控件通常作为对话框的子窗口而创建的,也出现在视类窗口、工具栏和状态条中。以后会陆陆续续介绍相应的控件。

7.1.2对话框的种类

对话框有两种类型:模态对话框和非模态对话框。
模态对话框:模态对话框显示的时候,程序会暂停执行。直到关闭这个对话框后,才能继续执行程序。	
非模态对话框:对话框显示时候,可以允许转而执行程序中的其他任务,而不用关闭这个对话框。

7.2对话框的创建

建立一个单文档工程,工程名为:Mybole。
运行,然后单击菜单栏帮助,就会出现一个帮助对话框。

创建自己的对话框:通过插入一个对话框资源来完成。
Insert->Resource->选中Dialog->New
在ResourceView选项Dialog项下就会出现标识为IDD_DIALOG1名称的对话框资源,同时在资源编辑窗口中打开了这个新对话框资源。如图所示
在这里插入图片描述
也可以单击资源工具栏上面->New Dialog按钮来新建一个对话框资源。

可以看到IDD_DIALOG1对话框有两个按钮:OK和Cancel。
他们ID分别为IDOK和IDCANCEL,VC++已经为这两个按钮提供了默认的消息响应函数OnOK和OnCancel。他们功能都是关闭对话框,但是单击不同按钮,用来确定或者取消当前操作。

打开IDD_DIALOG1对话框属性,将Caption属性设置为“测试”。
在MFC中,对资源的操作是通过一个与资源相关类来完成,对话框资源也有一个相应的基类:CDialog。
因此需要创建一个类与新建的对话框资源相关联:
View->ClassWizard,就会弹出一个对话框,提示IDD_DIALOG1对话框是一个新资源,需要为它创建一个相关联的类或者用已有的一个类与它相关联。这里选择前者,单击OK。就成功创建一个与IDD_DIALOG1对话框相关联的类。

单击OK后就会出现下图。
在这里插入图片描述
在Name编辑框中输入新类名称:CTestDlg,File Name自动出现文件名:TestDlg.cpp。
单击Change,可以改变新类的头文件名和源文件名。这里不做改变。

单击OK后,在ClassView选项中多了这个新类。并且CTestDlg这个类有两个成员函数:一个就是它的构造函数;一个是DoDateExchange函数。
构造函数:

CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CTestDlg::IDD, pParent)
{
 //{{AFX_DATA_INIT(CTestDlg)
  // NOTE: the ClassWizard will add member initialization here
 //}}AFX_DATA_INIT
}

CTestDlg构造函数先调用其基类:CDialog类的构造函数,传递两个参数:一个是CTestDlg类的IDD成员,即这个对话框资源ID;一个是父窗口指针。
DoDateExchange函数:

void CTestDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CTestDlg)
  // NOTE: the ClassWizard will add DDX and DDV calls here
 //}}AFX_DATA_MAP
}

完成对话框数据的交换和检验。

这样CTestDlg与IDD_DIALOG1对话框资源相关联了。接下来就是显示这个对话框窗口。
首先增加一个菜单项,当单击这个菜单项就显示该对话框:
在Mybole程序的帮助菜单项后面添加一个名为对话框的菜单项,单击菜单项属性,将Caption改为“对话框”,将Pop-up勾选去掉,ID为IDM_DIALOG。
接着利用ClassWizard为该菜单项添加COMMAND命令消息响应函数。让视类捕获命令响应,同时在该消息响应函数中实现对该对话框窗口的显示。

7.2.1模态对话框的创建

创建模态对话框,需要调用CDialog类的成员函数:DoModal,该函数的功能就是创建并且显示一个模态对话框。其返回值可以作为CDialog类另一个成员函数:EndDialog函数的参数,该函数的功能就是关闭模态对话框。

void CMyboleView::OnDialog() 
{
 // TODO: Add your command handler code here
 CTestDlg dlg;
 dlg.DoModal();
}

首先定义一个对话框对象,然后利用该对象调用DoModal函数。
同时视类源文件应该包含CTestDlg类的头文件。
#include “TestDlg.h”
运行,单击对话框菜单项,就出现下图。
在这里插入图片描述

7.2.2非模态对话框的创建

非模态对话框的创建,需要用到CDialog类的Create成员函数。
BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL );
BOOL Create( UINT nIDTemplate, CWnd* pParentWnd = NULL );
Create函数第一个参数可以是对话框模板的名称;或者是对话框资源的ID。第二个参数指定对话框的父窗口,若为NULL,对于本例来说就是框架窗口。

void CMyboleView::OnDialog() 
{
 // TODO: Add your command handler code here
 CTestDlg dlg;
 //dlg.DoModal();
 dlg.Create(IDD_DIALOG1,this);
 dlg.ShowWindow(SW_SHOW);
}

this表示对话框的父窗口就是视类窗口。
由于Create函数不具有显示对话框的功能,所以要调用ShowWindow函数。

运行,发现对话框并没有显示出来:是由于dlg是一个局部变量。
调用DoModal函数之所以会显示出来,是因为程序执行到该函数会停下来,dlg变量并没有销毁。
而调用ShowWindow,程序继续运行,dlg变量的生命周期在出了该消息响应函数后就结束了,所以对话框就消失了。

两种解决方法:
1、将该变量变成视类的成员变量。
2、将它定义为指针,在堆上分配内存。

void CMyboleView::OnDialog() 
{
 // TODO: Add your command handler code here
 //CTestDlg dlg;
 //dlg.DoModal();
 CTestDlg *pDlg=new CTestDlg;
 pDlg->Create(IDD_DIALOG1,this);
 pDlg->ShowWindow(SW_SHOW);
}

但是还有问题:pDlg变量仍然是一个局部变量,生命周期结束后,它保存的内存地址就丢失了。那么在程序中就无法引用那一块内存了。
解决方法:
1、将pDlg变量定义为视类的成员变量,同时在视类的析构函数中用Delete函数来释放这个指针变量所指向的内存。
2、在CTestDlg类中重载PostNcDestroy虚函数,释放this指针指向的内存。
鼠标单击视类右键->Add Virtue Function

void CTestDlg::PostNcDestroy() 
{
 // TODO: Add your specialized code here and/or call the base class
 delete this;
 CDialog::PostNcDestroy();
}

单击OK按钮时,模态对话框对象被销毁;而非模态对话框对象没有销毁,而是隐藏起来了。
因此,对于非模态对话框来说,如果有一个IDOK的按钮,就必须重写基类的OnOK虚函数,在重写的OnOK函数中调用DestroyWindows函数,完成对话框的销毁工作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值