网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
源代码在线查看: 07.2.2 非模态对话框的创建.txt
7.2.2 非模态对话框的创建
如果要创建非模态对话框,则需要利用 CDialog类的 Create成员函数。该函数具有以下两种形式的声明:
BOOL Create( LPCTSTR lpsZTemplateName, CWnd* pParentWnd = NULL );
BOOL Create( UINT n工 DTemplate, CWnd* pParentWnd = NULL );
也就是说, Create函数的第一个参数可以是对话框资源的 ID ( nIDTemplate参数 ),或者也可以是对话框模板的名称 ( lpszTemplateName参数)。这个函数的第二个参数指定了对话框的父窗口,如果其值是 NULL,对话框的父窗口就是主应用程序窗口。对本例来说,如果这个父窗口参数值是 NULL,对话框的父窗口就是框架窗口。这里,我们仍在 CMyboleView类 OnDialog函数中实现创建非模态对话框的功能,则首先需要将上面例 7-4所示代码中创建模态对话框的代码注释起来,然后在其后面添加创建非模态对话框的代
码,结果如例 7-6所示。
void CMyboleView: :OnDialog()
// TODO : Add your command handler code here /1 CTestDlg dlg; // dlg.DoModal();
CTestDlg dlg;
dlg.Create(IDD_DIALOG1,this) ;
Build井运行Mybole程序,单击程序菜单栏上的【对话框】菜单,发现并未出现测试对话框窗口。这里,读者一定要注意,当利用 Create画数创建非模态对话框时,还需要调用ShowWindow函数将这个对话框显示出来。那为什么上面利用DoModal函数创建对话框时不需要呢?这是因为DoModal函数本身就有显示模态对话框的作用,所以对模态对话框来说,不需要再调用ShowWindow函数来显示对话框了,但非模态对话框需要调用此函数。因此,我们在上述例7-6所示OnDialog函数的最后再加上下面这行代码:
dlg.ShowWindow(SW_SHOW);
Build井运行Mybole程序,单击程序菜单栏上的【对话框】菜单,发现仍没有出现测试对话框。问题出在哪里呢?我们回头看看上面的代码,发现这里创建的非模态对话框对象 (dlg)是一个局部对象,当程序执行时,会依次执行各条代码,当OnDialog函数的右大括号执行结束时, dlg这个对象的生命周期也就结束了,它就会销毁与之相关联的对话框资源。那为什么上面创建模态对话框时就可以使用局部对象呢?上面已经讲过,在创建模态对话框时,当执行到调用DoModal函数以显示这个对话框时,程序就会暂停执行,直到模态对话框关闭之后,程序才继续向下执行。也就是说,当模态对话框显示时,程序中创建的dlg这个对象的生命周期并未结束。因此,在创建非模态对话框时,不能把对话框对象定义为局部对象。对于这个问题,有两种解决办法:一种就是把这个对话框对象定义为视类的成员变量:另一种方式是将它定义为指针,在堆上分配内存。我们知道,在堆上分配的内存,与程序的整个生命周期是一致的,当然这里是指程序中不主动销毁的情况。这里,我们采用后一种方式,修改己有代码,结果如例7-7所示。
例7-7
void CMyboleView : :OnDialog()
.
// TODO: Add your command handler code here 11 CTestDlg dlg ; // dlg . DoModal();
CTestDlg *pDlg = new CTestDlg;
pDlg->Create(IDD_DIALOG1, this);
pDlg->ShowWindow(SW_SHOW) ;
因为这里定义的对话时象是指针类型,所有调用其成员函数时应该
用->操作符。
Build并运行Mybole程序,单击程序菜单栏上的【对话框】菜单,测试对话框出现了,这时可以试着单击程序的菜单项,将会发现可以进行这项操作,如图7.11所示。这就是非模态对话框的特点。因为程序显示非模态对话框时,并不会停留在某条语句处,所以 CMyboleView类的 OnDialog函数内部的代码就会顺序地被执行,直到该函数执行结束,. 这时,程序就可以执行其他任务了,例如响应菜单项的单击操作。
图 7.11非模态对话框的显示
可是,上述例7-7所示的这段程序仍有问题,首先,我们定义的pDlg这个指针变量是一个局部对象,这样当它的生命周期结束时,它所保存的内存地址就丢失了,那么在程序中也就无法再引用到它所指向的那块内存了。这个问题的解决办法有两种:一是将这个指针变量定义为视类 C CMyboleView )的成员变量,然后在CMyboleView类的析构函数中调用 delete函数来释放这个指针变量所指向的那块内存:二是在 CTestDlg类中重载 PostNcDestroy虚函数,释放this指针所指向的内存,代码如例7-8所示,其中加灰显示的代码是我们添加的代码。
~~ 7-8
void CTestDlg :: PostNcDestroy()
// TODO: Add your specialized code here and/ or call the base class delete this; CDialog : :PostNcDestroy();
另外,读者会发现上述示例中无论创建的是模态对话框,还是非模态对话框,当单击对话框上的【OK】按钮时,对话框都会消失。但有一点需要提醒读者注意,对模态对话框而言,此时对话框窗口对象被销毁了。而对非模态对话框来说,对话框窗口对象并未被销毁,只是隐藏起来了。我们来分析一下在非模态对话框中单击OK按钮后,程序所发生的事情。这时,程序会调用基类 CCDialog)的 OnOK函数,这是一个虚函数。后者又会
调用EndDialog函数,这个函数用于终止模态对话框,而对于非模态对话框,这个函数只是使对话框窗口不可见,并不销毁它。因此,对非模态对话框来说,如果有一个 E值为 IDOK的按钮,就必须重写基类的 OnOK这个虚函数,并在重写的函数中调用 DestroyWindow函数,以完成销毁对话框的工作,同时注意不要再调用基类的OnOK函数。同样地,如果非模态对话框中有一个 ID值为 IDCANCEL的按钮,也必须重写基类的 OnCancel虚函数,并在重写的函数中调用Des位oyWindow函数,销毁对话框,同时注意不要再调用基类的OnCancel函数。