⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap5_4.htm

📁 着重介绍基于C++的web编程技术
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>5.4 非模态对话框</title>
</head>

<body link="#3973DE" alink="#3973DE">
<font SIZE="5"><b><div align="center"><center>

<table border="0" width="615" cellspacing="0" cellpadding="0">
  <tr>
    </b><td><div align="center"><center><table border="0" width="615" cellpadding="0" cellspacing="0" height="20">
      <tr>
        <td width="377" bgcolor="#15397D" height="20"></td>
        <td width="238" bgcolor="#000000" height="20"><p align="right"></font><span style="text-decoration: none"><a href="../../index.htm"><font color="#FFFFFF">电脑报Visual 
        C++网络教程</font></a></span></td>
      </tr>
    </table>
    </center></div><font FACE="Times New Roman" SIZE="3"><b><p ALIGN="CENTER"></b></font><font FACE="Times New Roman" size="4" color="#3973DE">5.4 </font><font size="4" color="#3973DE">非模态对话框</font><font FACE="Times New Roman" size="4"></p>
    <p ALIGN="JUSTIFY"></font><font color="#3973DE"><font FACE="Times New Roman" SIZE="3">5.4.1 
    </font><font SIZE="3">非模态对话框的特点</font></font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">与模态对话框不同,非模态对话框不垄断用户的输入,用户打开非模态对话框后,仍然可以与其它界面进行交互。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">非模态对话框的设计与模态对话框基本类似,也包括设计对话框模板和设计</font><font FACE="Times New Roman" SIZE="3">CDialog</font><font SIZE="3">类的派生类两部分。但是,在对话框的创建和删除过程中,非模态对话框与模态对话框相比有下列不同之处:</p>
    <ul>
      <li><p ALIGN="JUSTIFY">非模态对话框的模板必须具有<font FACE="Times New Roman" SIZE="3">Visible</font>风格,否则对话框将不可见,而模态对话框则无需设置该项风格。更保险的办法是调用<font FACE="Times New Roman" SIZE="3">CWnd::ShowWindow(SW_SHOW)</font>来显示对话框,而不管对话框是否具有<font FACE="Times New Roman" SIZE="3">Visible</font>风格。</p>
      </li>
      <li><p ALIGN="JUSTIFY">非模态对话框对象是用<font FACE="Times New Roman" SIZE="3">new</font>操作符在堆中动态创建的,而不是以成员变量的形式嵌入到别的对象中或以局部变量的形式构建在堆栈上。通常应在对话框的拥有者窗口类内声明一个指向对话框类的指针成员变量,通过该指针可访问对话框对象。</p>
      </li>
      <li><p ALIGN="JUSTIFY">通过调用<font FACE="Times New Roman" SIZE="3">CDialog::Create</font>函数来启动对话框,而不是<font FACE="Times New Roman" SIZE="3">CDialog::DoModal</font>,这是模态对话框的关键所在。由于<font FACE="Times New Roman" SIZE="3">Create</font>函数不会启动新的消息循环,对话框与应用程序共用同一个消息循环,这样对话框就不会垄断用户的输入。<font FACE="Times New Roman" SIZE="3">Create</font>在显示了对话框后就立即返回,而<font FACE="Times New Roman" SIZE="3">DoModal</font>是在对话框被关闭后才返回的。众所周知,在<font FACE="Times New Roman" SIZE="3">MFC</font>程序中,窗口对象的生存期应长于对应的窗口,也就是说,不能在未关闭屏幕上窗口的情况下先把对应的窗口对象删除掉。由于在<font FACE="Times New Roman" SIZE="3">Create</font>返回后,不能确定对话框是否已关闭,这样也就无法确定对话框对象的生存期,因此只好在堆中构建对话框对象,而不能以局部变量的形式来构建之。</p>
      </li>
      <li><p ALIGN="JUSTIFY">必须调用<font FACE="Times New Roman" SIZE="3">CWnd::DestroyWindow</font>而不是<font FACE="Times New Roman" SIZE="3">CDialog::EndDialog</font>来关闭非模态对话框。调用<font FACE="Times New Roman" SIZE="3">CWnd::DestroyWindow</font>是直接删除窗口的一般方法。由于缺省的<font FACE="Times New Roman" SIZE="3">CDialog::OnOK</font>和<font FACE="Times New Roman" SIZE="3">CDialog::OnCancel</font>函数均调用<font FACE="Times New Roman" SIZE="3">EndDialog</font>,故程序员必须编写自己的<font FACE="Times New Roman" SIZE="3">OnOK</font>和<font FACE="Times New Roman" SIZE="3">OnCancel</font>函数并且在函数中调用<font FACE="Times New Roman" SIZE="3">DestroyWindow</font>来关闭对话框。</p>
      </li>
      <li><p ALIGN="JUSTIFY">因为是用<font FACE="Times New Roman" SIZE="3">new</font>操作符构建非模态对话框对象,因此必须在对话框关闭后,用<font FACE="Times New Roman" SIZE="3">delete</font>操作符删除对话框对象。在屏幕上一个窗口被删除后,框架会调用<font FACE="Times New Roman" SIZE="3">CWnd::PostNcDestroy</font>,这是一个虚拟函数,程序可以在该函数中完成删除窗口对象的工作,具体代码如下<br>
        <font FACE="Times New Roman" SIZE="3">void CModelessDialog::PostNcDestroy<br>
        {<br>
        delete this; //</font>删除对象本身<br>
        <font FACE="Times New Roman" SIZE="3">}<br>
        </font>这样,在删除屏幕上的对话框后,对话框对象将被自动删除。拥有者对象就不必显式的调用<font FACE="Times New Roman" SIZE="3">delete</font>来删除对话框对象了。</p>
      </li>
      <li><p ALIGN="JUSTIFY">必须有一个标志表明非模态对话框是否是打开的。这样做的原因是用户有可能在打开一个模态对话框的情况下,又一次选择打开命令。程序根据标志来决定是打开一个新的对话框,还是仅仅把原来打开的对话框激活。通常可以用拥有者窗口中的指向对话框对象的指针作为这种标志,当对话框关闭时,给该指针赋<font FACE="Times New Roman" SIZE="3">NULL</font>值,以表明对话框对象已不存在了。</p>
      </li>
    </ul>
    <b><div align="center"><center><table border="2" cellpadding="2" cellspacing="0" width="90%" bgcolor="#8CDAFF">
      <tr>
        </b><td width="100%">提示:在</font><font FACE="Times New Roman" SIZE="3">C++</font><font SIZE="3">编程中,判断一个位于堆中的对象是否存在的常用方法是判断指向该对象的指针是否为空。这种机制要求程序员将指向该对象的指针初始化为</font><font FACE="Times New Roman" SIZE="3">NULL</font><font SIZE="3">值,在创建对象时将返回的地址赋给该指针,而在删除对象时将该指针置成</font><font FACE="Times New Roman" SIZE="3">NULL</font><font SIZE="3">值。</font></td>
      </tr>
    </table>
    </center></div><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY"></font><font SIZE="3">根据上面的分析,我们很容易把</font><font FACE="Times New Roman" SIZE="3">Register</font><font SIZE="3">程序中的登录数据对话框改成非模态对话框。这样做的好处在于如果用户在输入数据时发现编辑视图中有错误的数据,那么不必关闭对话框,就可以在编辑视图中进行修改。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3">请读者按下面几步操作:</p>
    <blockquote>
      <blockquote>
        <p ALIGN="JUSTIFY">在登录数据对话框模板的属性对话框的</font><font FACE="Times New Roman" SIZE="3">More Styles</font><font SIZE="3">页中选择</font><font FACE="Times New Roman" SIZE="3">Visible</font><font SIZE="3">项。</p>
        <p ALIGN="JUSTIFY">在</font><font FACE="Times New Roman" SIZE="3">RegisterView.h</font><font SIZE="3">头文件的</font><font FACE="Times New Roman" SIZE="3">CRegisterView</font><font SIZE="3">类的定义中加入<br>
        </font><font FACE="Times New Roman" SIZE="3"><b>public:<br>
        CRegisterDialog* m_pRegisterDlg;</p>
        </b></font><font SIZE="3"><p ALIGN="JUSTIFY">在</font><font FACE="Times New Roman" SIZE="3">RegisterView.h</font><font SIZE="3">头文件的头部加入对</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">类的声明<br>
        </font><font FACE="Times New Roman" SIZE="3"><b>class CRegisterDialog;<br>
        </b></font><font SIZE="3">加入该行的原因是在</font><font FACE="Times New Roman" SIZE="3">CRegisterView</font><font SIZE="3">类中有一个</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">类型的指针,因此必须保证</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">类的声明出现在</font><font FACE="Times New Roman" SIZE="3">CRegisterView</font><font SIZE="3">之前,否则编译时将会出错。解决这个问题有两种办法,一种办法是保证在</font><font FACE="Times New Roman" SIZE="3">#include </font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">RegisterView.h</font><font SIZE="3">”语句之前有</font><font FACE="Times New Roman" SIZE="3">#include </font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">RegisterDialog.h</font><font SIZE="3">”语句,这种办法造成了一种依赖关系,增加了编译负担,不是很好;另一种办法是在</font><font FACE="Times New Roman" SIZE="3">CRegisterView</font><font SIZE="3">类的声明之前加上一个对</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">的声明来暂时“蒙蔽”编译器,这样在有</font><font FACE="Times New Roman" SIZE="3">#include </font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">RegisterView.h</font><font SIZE="3">”语句的模块中,除非要用到</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">类,否则不用加入</font><font FACE="Times New Roman" SIZE="3">#include </font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">RegisterDialog.h</font><font SIZE="3">”语句。</p>
        <p ALIGN="JUSTIFY">在</font><font FACE="Times New Roman" SIZE="3">RegisterDialog.cpp</font><font SIZE="3">文件的头部的</font><font FACE="Times New Roman" SIZE="3">#include</font><font SIZE="3">语句区的末尾添加下面两行<br>
        </font><font FACE="Times New Roman" SIZE="3"><b>#include &quot;RegisterDoc.h&quot;<br>
        #include &quot;RegisterView.h&quot;</p>
        </b></font><font SIZE="3"><p ALIGN="JUSTIFY">利用</font><font FACE="Times New Roman" SIZE="3">ClassWizard</font><font SIZE="3">为</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">类加入</font><font FACE="Times New Roman" SIZE="3">OnCancel</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">PostNcDestroy</font><font SIZE="3">成员函数。加入的方法是进入</font><font FACE="Times New Roman" SIZE="3">ClassWizard</font><font SIZE="3">后选择</font><font FACE="Times New Roman" SIZE="3">Message Maps</font><font SIZE="3">页,并在</font><font FACE="Times New Roman" SIZE="3">Class name</font><font SIZE="3">栏中选择</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">。然后,在</font><font FACE="Times New Roman" SIZE="3">Object IDs</font><font SIZE="3">栏中选择</font><font FACE="Times New Roman" SIZE="3">IDCANCEL</font><font SIZE="3">后,在</font><font FACE="Times New Roman" SIZE="3">Messages</font><font SIZE="3">栏中双击</font><font FACE="Times New Roman" SIZE="3">BN_CLICKED</font><font SIZE="3">,这就创建了</font><font FACE="Times New Roman" SIZE="3">OnCancel</font><font SIZE="3">。要创建</font><font FACE="Times New Roman" SIZE="3">PostNcDestroy</font><font SIZE="3">,先在</font><font FACE="Times New Roman" SIZE="3">Object IDs</font><font SIZE="3">栏中选择</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">,再在</font><font FACE="Times New Roman" SIZE="3">Messages</font><font SIZE="3">栏中双击</font><font FACE="Times New Roman" SIZE="3">PostNcDestroy</font><font SIZE="3">即可。</p>
        <p ALIGN="JUSTIFY">分别按清单</font><font FACE="Times New Roman" SIZE="3">5.10</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">5.11</font><font SIZE="3">,对</font><font FACE="Times New Roman" SIZE="3">CRegisterView</font><font SIZE="3">类和</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog</font><font SIZE="3">类进行修改。</p>
        </font>
      </blockquote>
    </blockquote>
    <p><b><font SIZE="3"> </p>
    <p ALIGN="JUSTIFY">清单</font><font FACE="Times New Roman" SIZE="3">5.10 CRegisterView</font><font SIZE="3">类的部分代码</font></b><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">CRegisterView::CRegisterView()</p>
    <p ALIGN="JUSTIFY">{</p>
    <p ALIGN="JUSTIFY">// TODO: add construction code here</p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">m_pRegisterDlg=NULL; //</font><font SIZE="3">指针初始化为</font><font FACE="Times New Roman" SIZE="3">NULL</b></p>
    <p ALIGN="JUSTIFY">}</p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">void CRegisterView::OnEditRegister() </p>
    <p ALIGN="JUSTIFY">{</p>
    <p ALIGN="JUSTIFY">// TODO: Add your command handler code here</p>
    <p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">if(m_pRegisterDlg)</p>
    <p ALIGN="JUSTIFY">m_pRegisterDlg-&gt;SetActiveWindow(); //</font><font SIZE="3">激活对话框</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">else</p>
    <p ALIGN="JUSTIFY">{</p>
    <p ALIGN="JUSTIFY">//</font><font SIZE="3">创建非模态对话框</font><font FACE="Times New Roman" SIZE="3"></p>
    <p ALIGN="JUSTIFY">m_pRegisterDlg=new CRegisterDialog(this);</p>
    <p ALIGN="JUSTIFY">m_pRegisterDlg-&gt;Create(IDD_REGISTER,this);</p>
    <p ALIGN="JUSTIFY">}</b></p>
    <p ALIGN="JUSTIFY">}<br>
    </p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -