对话框编程

创建和使用对话框

在程序中创建和使用对话框
向现有程序中插入一个新的对话框资源(Ctrl+R)

添加新对话框后,资源管理器中就会出现新的对话框,并且有一个空对话框界面。
在对话框上右键属性(alt+Enter),修改ID和各项属性。
拖动控件到新的对话框内,与之前控件使用方法完全一致。
为新创建的对话框添加对应的Dlg类
在MyDlg1对话框中启动类向导(Ctrl+W),弹出询问

为新创建的对话框添加对应的Dlg类
在这里起名字的时候,最好以"C"开头

布置新的对话框中的控件,
启动类向导:添加控件变量,处理所有控件的消息响应
启动类向导:为类添加WM_INITDIALOG消息响应,添加默认的初始化函数OnInitDialog()
到此,就已经在程序中添加了一个新的对话框。程序原有的对话框,一般称为主/父对话框,新建的对话框又称为子对话框。
新添加的对话框,实际上是一个类,需要在主对话框中声明一个对话框变量,然后启动该对话框,才能使用。
回顾:Dlg程序运行的步骤:
MFC的WinMain函数中,通过多态找到当前程序的App对象,调用其InitInstance函数,并且在其中实现如下代码:
CW6_1Dlg dlg;
m_pMainWnd = &dlg;
Int nResponse = dlg.DoModal();
If(nRespone == IDOK){
//TODO: Place code here to han
类似,通过在父对话框中使用MyDlg类对象,执行DoModal()方法,就可以显示出对话框。
#include “stdafx.h”
#include “W6_1.h”
#include “W6_1Dlg.h”
#include “MyDlg1.h”
首先,在主窗口的Dlg.cpp文件中 #include 新建对话框的头文件
然后在一个按钮控件的响应函数中写代码,就可以显示出新的对话框。
Void CW6_1Dlg::OnButton1(){
CMyDlg1 dlg;
If(dlg.DoModal()==IDOK){
MessageBox(“OK”):
}else{
MessageBox(“Cancel”);
}
主窗口通过DoModal方法启动子窗口后 ,失去消息循环,进入等待。直到用户点击子窗口中的确定或者取消后,子窗口关闭,主窗口恢复到前台。
点击子窗口的确定按钮,会自动执行updatedata(true),并向DoModal返回IDOK。
当点击取消按钮时,子窗口直接关闭,返回IDCANCLE
主窗口首先判断DoModal的返回值,然后数据读取。

对话框之间的数据传输

第一种模式:从主窗口中读取子窗口的数据

对于Value类型的控件数据,如编辑框,在子窗口点击“确定”按钮后,能够自动更新,因此可以直接读取
CMyDlg1 dlg1;
If(dlg1.DoModal()==IDOK){
Cstring dlgstring=dlg1.m_strEdit;
MessageBox(dlgstring);
}
对于Control类型的控件,如滑块,可以在子窗口类中添加一个成员变量,在关闭窗口前手动保存该数据,即可。
例子:在子对话框中建立一个滑块控件,点击确定后,主窗口中读取该滑块值。
Step1:在子窗口类中,声明一个public类型的 int变量
Step2:在滑块的消息响应函数中,实时修改该int变量
Step3:在主窗口中直接读取int变量。
第二种模式:在子窗口中修改父窗口数据(把数据填入主窗口)
观察窗口类的构造函数,其带有一个参数,该参数指明了其父窗口的窗口类指针。
class CMyDlg1 : public CDialog
{
// Construction
public:
 CMyDlg1(CWnd* pParent = NULL);   // standard constructor
创建子窗口时,如果指定了该参数,那么在子窗口中就可以根据该指针调用父窗口的各类对象。
Step1: 在子窗口类中添加父窗口类的指针:
CWnd*  m_pParent;
Setp2: 在子窗口的构造函数中,初始化该指针:
CMyDlg1::CMyDlg1(CWnd* pParent /*=NULL*/)
 : CDialog(CMyDlg1::IDD, pParent)
{
 //{{AFX_DATA_INIT(CMyDlg1)
 m_strMyEdit = _T("");
 m_nCurSliderPos = 0;
 m_pParent = pParent;
 //}}AFX_DATA_INIT
}
子窗口中修改父窗口数据(把数据填入主窗口)
Step3: 在父窗口中,利用this指针创建子窗口对象,
CMyDlg    dlg(this);
Step4:遍写子窗口代码,在一个按钮响应函数中,将编辑框内容读出,写入主窗口中的列表框。
void CMyDlg1::OnButton1() 
{
 UpdateData(true);
 if (m_pParent != NULL)
  {
  CListBox *pListBox ;
  pListBox = (CListBox*)m_pParent->GetDlgItem(IDC_LIST1);
  pListBox->AddString(m_strMyEdit);
 }
 m_strMyEdit = "";
 UpdateData(false);
}
思考如下问题:
假如程序的主窗口中,启动了一项工作(如定时器),需要消耗一些时间。现在希望通过子窗口中的进度条来显示这项工作执行的进度,应该怎样实现?分哪几个步骤?
提示:利用子窗口中的定时器

模式对话框和无模式对话框

所谓“模式对话框”,是指当对话框被弹出时,用户必须在对话框作出相应的操作,在退出对话框前,其父窗口无法操作。
模式对话框一般需要有“确定”和“取消”两个按钮,通知其父窗口,用户在对话框内的操作是否有效。
我们之前使用的dlg程序,其实就是一个模式对话框。本节课介绍的dlg.DoModal() 方法,是在程序中生成一个模式对话框的标准方法。
与模式对话框相对应,“无模式对话框”是指当对话框被弹出后,一直保留在屏幕中,可以随时被激活,不影响其父窗口的使用。
无模式对话框,相当于一个程序拥有了多个可操作界面。灵活性增加,但也容易造成混乱。
与使用模式对话框的区别:
创建方法不同:需要自己编写对话框创建、显示代码
void CW6_1Dlg::OnButton1(){
CMyDlg1* pMydlg = new CMyDlg1;//创建一个类对象
pMydlg->m_pParent = this;//指定其父指针
pMydlg->Create(IDD_MY_DIALOG1);//创建对话框
pMydlg->Showwindow(SW_NORMAL);//显示对话框
退出方法不同:需要自己处理内存,删除对象
void CMyDlg1::OnOK() 
{
 DestroyWindow();
 delete this; 
 //CDialog::OnOK();
}
void CMyDlg1::OnCancel() 
{
 // TODO: Add extra cleanup here
 DestroyWindow();
 delete this;
 
 //CDialog::OnCancel();
}
在子对话框中双击确定、退出按钮,添加默认的响应函数,在其中添加两行代码,实现退出时的内存清理。
由于不是通过DoModal方法创建窗口,因此主窗口仍然可以操作。
在任何时候,主窗口中都可以通过所创建的对话框对象指针来读取窗口内控件数据和变量数据。
反之,在子窗口中也同样可以通过指定其父窗口指针来实现数据写入和读取。

Related Articles

Quote Of The Day