📄 chap5_3.htm
字号:
<p ALIGN="JUSTIFY">m_strIncome = _T("");</p>
<p ALIGN="JUSTIFY">m_strKind = _T("");</p>
<p ALIGN="JUSTIFY">m_bMarried = FALSE;</p>
<p ALIGN="JUSTIFY">m_strName = _T("");</p>
<p ALIGN="JUSTIFY">m_nSex = -1;</p>
<p ALIGN="JUSTIFY">m_strUnit = _T("");</p>
<p ALIGN="JUSTIFY">m_nWork = -1;</p>
<p ALIGN="JUSTIFY">//}}AFX_DATA_INIT</p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p></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">ClassWizard</font><font SIZE="3">自动完成的。若读者对初值的含义还不太清楚,请参看表</font><font FACE="Times New Roman" SIZE="3">5.3</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">WM_INITDIALOG</font><font SIZE="3">消息,对话框对该消息的处理函数是</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">。调用</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">时,对话框已初步创建,对话框的窗口句柄也已有效,但对话框还未被显示出来。因此,可以在</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">中做一些影响对话框外观的初始化工作。</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">对对话框的作用与</font><font FACE="Times New Roman" SIZE="3">OnCreate</font><font SIZE="3">对</font><font FACE="Times New Roman" SIZE="3">CMainFrame</font><font SIZE="3">的作用类似。</font><font FACE="Times New Roman" SIZE="3"></p>
</font><font SIZE="3"><div align="center"><center><table border="2" cellpadding="2" cellspacing="0" width="90%" bgcolor="#A6C0F0">
<tr>
<td width="100%">提示</font><font FACE="Times New Roman" SIZE="3">:MFC</font><font SIZE="3">窗口的初始化工作一般在</font><font FACE="Times New Roman" SIZE="3">OnCreate</font><font SIZE="3">成员函数中进行,但对话框的初始化工作最好在</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">中进行。</font></td>
</tr>
</table>
</center></div><font FACE="Times New Roman" SIZE="3"><p ALIGN="JUSTIFY">OnInitDialog</font><font SIZE="3">是</font><font FACE="Times New Roman" SIZE="3">WM_INITDIALOG</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">RegisteritDialog</font><font SIZE="3">类增加一个</font><font FACE="Times New Roman" SIZE="3">WM_INITDIALOG</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">MessageMaps</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">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">WM_INITDIALOG</font><font SIZE="3">并双击之,最后按</font><font FACE="Times New Roman" SIZE="3">OK</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"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">请读者按清单</font><font FACE="Times New Roman" SIZE="3">5.2</font><font SIZE="3">修改</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">函数。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </p>
<p ALIGN="JUSTIFY">清单</font><font FACE="Times New Roman" SIZE="3">5.2 OnInitDialog</font><font SIZE="3">函数</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">BOOL CRegisterDialog::OnInitDialog() </p>
<p ALIGN="JUSTIFY">{</p>
<p ALIGN="JUSTIFY">CDialog::OnInitDialog();</p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">// TODO: Add extra initialization here</p>
<p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">m_ctrlIncome.AddString("500</font><font SIZE="3">元以下</font><font FACE="Times New Roman" SIZE="3">");</p>
<p ALIGN="JUSTIFY">m_ctrlIncome.AddString("500-1000</font><font SIZE="3">元</font><font FACE="Times New Roman" SIZE="3">");</p>
<p ALIGN="JUSTIFY">m_ctrlIncome.AddString("1000-2000</font><font SIZE="3">元</font><font FACE="Times New Roman" SIZE="3">");</p>
<p ALIGN="JUSTIFY">m_ctrlIncome.AddString("2000</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"></p>
<p ALIGN="JUSTIFY">return TRUE; // return TRUE unless you set the focus to a control</p>
<p ALIGN="JUSTIFY">// EXCEPTION: OCX Property Pages should return FALSE</p>
<p ALIGN="JUSTIFY">}</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"></p>
<p ALIGN="JUSTIFY">CRegisterDialog::OnInitDialog()</font><font SIZE="3">的主要任务是对工资收入列表框的列表项进行初始化。调用</font><font FACE="Times New Roman" SIZE="3">CListBox::AddString</font><font SIZE="3">可将指定的字符串加入到列表框中。由于该列表是不自动排序的,因此</font><font FACE="Times New Roman" SIZE="3">AddString</font><font SIZE="3">将表项加在列表框的末尾。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font color="#3973DE" FACE="Times New Roman" SIZE="3">5.3.4</font><font SIZE="3" color="#3973DE">对话框的数据交换机制</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">MFC</font><font SIZE="3">提供了类</font><font FACE="Times New Roman" SIZE="3">CDataExchange</font><font SIZE="3">来实现对话框类与控件之间的数据交换</font><font FACE="Times New Roman" SIZE="3">(DDX)</font><font SIZE="3">,该类还提供了数据有效机制</font><font FACE="Times New Roman" SIZE="3">(DDV)</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::DoDataExchange</font><font SIZE="3">来完成。读者可以找到</font><font FACE="Times New Roman" SIZE="3">CRegisterDialog::DoDataExchange</font><font SIZE="3">函数,如清单</font><font FACE="Times New Roman" SIZE="3">5.3</font><font SIZE="3">所示。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </p>
<p ALIGN="JUSTIFY">清单</font><font FACE="Times New Roman" SIZE="3">5.3 DoDataExchange</font><font SIZE="3">函数</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">void CRegisterDialog::DoDataExchange(CDataExchange* pDX)</p>
<p ALIGN="JUSTIFY">{</p>
<p ALIGN="JUSTIFY">CDialog::DoDataExchange(pDX);</p>
<p ALIGN="JUSTIFY">//{{AFX_DATA_MAP(CRegisterDialog)</p>
<p ALIGN="JUSTIFY">DDX_Control(pDX, IDC_INCOME, m_ctrlIncome);</p>
<p ALIGN="JUSTIFY">DDX_LBString(pDX, IDC_INCOME, m_strIncome);</p>
<p ALIGN="JUSTIFY">DDX_CBString(pDX, IDC_KIND, m_strKind);</p>
<p ALIGN="JUSTIFY">DDX_Check(pDX, IDC_MARRIED, m_bMarried);</p>
<p ALIGN="JUSTIFY">DDX_Text(pDX, IDC_NAME, m_strName);</p>
<p ALIGN="JUSTIFY">DDX_Radio(pDX, IDC_SEX, m_nSex);</p>
<p ALIGN="JUSTIFY">DDX_Text(pDX, IDC_UNIT, m_strUnit);</p>
<p ALIGN="JUSTIFY">DDX_Radio(pDX, IDC_WORK, m_nWork);</p>
<p ALIGN="JUSTIFY">DDX_Text(pDX, IDC_AGE, m_nAge);</p>
<p ALIGN="JUSTIFY">DDV_MinMaxUInt(pDX, m_nAge, 16, 65);</p>
<p ALIGN="JUSTIFY">//}}AFX_DATA_MAP</p>
<p ALIGN="JUSTIFY">}</p>
<p ALIGN="JUSTIFY"></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">DoDataExchange</font><font SIZE="3">只有一个参数,即一个</font><font FACE="Times New Roman" SIZE="3">CDataExchange</font><font SIZE="3">对象的指针</font><font FACE="Times New Roman" SIZE="3">pDX</font><font SIZE="3">。在该函数中调用了</font><font FACE="Times New Roman" SIZE="3">DDX</font><font SIZE="3">函数来完成数据交换,调用</font><font FACE="Times New Roman" SIZE="3">DDV</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">DoDataExchange</font><font SIZE="3">函数,而应该调用</font><font FACE="Times New Roman" SIZE="3">CWnd::UpdateData</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3">UpdataData</font><font SIZE="3">函数内部调用了</font><font FACE="Times New Roman" SIZE="3">DoDataExchange</font><font SIZE="3">。该函数只有一个布尔型参数,它决定了数据传送的方向。调用</font><font FACE="Times New Roman" SIZE="3">UpdateData(TRUE)</font><font SIZE="3">将数据从对话框的控件中传送到对应的数据成员中,调用</font><font FACE="Times New Roman" SIZE="3">UpdateData(FALSE)</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::OnInitDialog</font><font SIZE="3">中调用了</font><font FACE="Times New Roman" SIZE="3">UpdateData(FALSE)</font><font SIZE="3">,这样,在对话框创建时,数据成员的初值就会反映到相应的控件上。若用户是按了</font><font FACE="Times New Roman" SIZE="3">OK</font><font SIZE="3">(确定)按钮退出对话框,则对话框认为输入有效,就会调用</font><font FACE="Times New Roman" SIZE="3">UpdataData(TRUE)</font><font SIZE="3">将控件中的数据传给数据成员。图</font><font FACE="Times New Roman" SIZE="3">5.9</font><font SIZE="3">描绘了对话框的这种数据交换机制。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="CENTER"></font><font SIZE="3"><img src="T5_9.gif" alt="T5_9.tif (186424 bytes)" WIDTH="547" HEIGHT="324"></font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="center"></font><font SIZE="3">图</font><font FACE="Times New Roman" SIZE="3">5.9
</font><font SIZE="3">对话框的数据交换</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font color="#3973DE" FACE="Times New Roman" SIZE="3">5.3.5</font><font SIZE="3" color="#3973DE">对话框的运行机制</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">在程序中运行模态对话框有两个步骤:</p>
<blockquote>
<p ALIGN="JUSTIFY">在堆栈上以变量的形式构建一个对话框对象。</p>
<p ALIGN="JUSTIFY">调用<font FACE="Times New Roman" SIZE="3">CDialog::DoModal ( )</font>。</font></p>
</blockquote>
<p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">DoModal</font><font SIZE="3">负责对模态话框的创建和撤销。在创建对话框时,</font><font FACE="Times New Roman" SIZE="3">DoModal</font><font SIZE="3">的任务包括载入对话框模板资源、调用</font><font FACE="Times New Roman" SIZE="3">OnInitDialog</font><font SIZE="3">初始化对话框和将对话框显示在屏幕上。完成对话框的创建后,</font><font FACE="Times New Roman" SIZE="3">DoModal</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">ID</font><font SIZE="3">为</font><font FACE="Times New Roman" SIZE="3">IDOK</font><font SIZE="3">的按钮(通常该按钮的标题是“确定”或“</font><font FACE="Times New Roman" SIZE="3">OK</font><font SIZE="3">”),或按了回车键,则</font><font FACE="Times New Roman" SIZE="3">CDialog::OnOK</font><font SIZE="3">将被调用。</font><font FACE="Times New Roman" SIZE="3">OnOK</font><font SIZE="3">首先调用</font><font FACE="Times New Roman" SIZE="3">UpdateData(TRUE)</font><font SIZE="3">将数据从控件传给对话框成员变量,然后调用</font><font FACE="Times New Roman" SIZE="3">CDialog::EndDialog</font><font SIZE="3">关闭对话框。关闭对话框后,</font><font FACE="Times New Roman" SIZE="3">DoModal</font><font SIZE="3">会返回值</font><font FACE="Times New Roman" SIZE="3">IDOK</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">ID</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">Cancel</font><font SIZE="3">”),或按了</font><font FACE="Times New Roman" SIZE="3">ESC</font><font SIZE="3">键,则会导致</font><font FACE="Times New Roman" SIZE="3">CDialog::OnCancel</font><font SIZE="3">的调用。该函数只调用</font><font FACE="Times New Roman" SIZE="3">CDialog::EndDialog</font><font SIZE="3">关闭对话框。关闭对话框后,</font><font FACE="Times New Roman" SIZE="3">DoModal</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"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">程序根据</font><font FACE="Times New Roman" SIZE="3">DoModal</font><font SIZE="3">的返回值是</font><font FACE="Times New Roman" SIZE="3">IDOK</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"></p>
<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">首先,将</font><font FACE="Times New Roman" SIZE="3">Register</font><font SIZE="3">工程的工作区切换至资源视图。打开</font><font FACE="Times New Roman" SIZE="3">IDR_MAINFRAME</font><font SIZE="3">菜单资源,在</font><font FACE="Times New Roman" SIZE="3">Edit</font><font SIZE="3">菜单的底端加入一个名为“登录数据”的新菜单项,并令其</font><font FACE="Times New Roman" SIZE="3">ID</font><font SIZE="3">为</font><font FACE="Times New Roman" SIZE="3">ID_EDIT_REGISTER</font><font SIZE="3">(最好在该项之前加一条分隔线,以便和前面的菜单项分开)。注意不要忘了把菜单资源的语种设置成中文,否则菜单中将显示不出中文来。设置的方法是先在工作区资源视图中选择</font><font FACE="Times New Roman" SIZE="3">IDR_MAINFRAME</font><font SIZE="3">菜单资源,然后按</font><font FACE="Times New Roman" SIZE="3">Alt+Enter</font><font SIZE="3">键,并在弹出的属性对话框中的</font><font FACE="Times New Roman" SIZE="3">Language</font><font SIZE="3">栏中选择</font><font FACE="Times New Roman" SIZE="3">Chinese(P.R.C.)</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">ClassWizard</font><font SIZE="3">为该菜单命令创建命令处理函数</font><font FACE="Times New Roman" SIZE="3">CRegisterView::OnEditRegister</font><font SIZE="3">。注意,</font><font FACE="Times New Roman" SIZE="3">OnEditRegister</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">CRegisterView</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">RegisterView.cpp</font><font SIZE="3">文件的开头加入下面一行</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">#include "RegisterDialog.h"</p>
<p ALIGN="JUSTIFY"></font><font SIZE="3">最后,按清单</font><font FACE="Times New Roman" SIZE="3">5.4</font><font SIZE="3">修改程序。</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY"></font><font SIZE="3"> </p>
<p ALIGN="JUSTIFY">清单</font><font FACE="Times New Roman" SIZE="3">5.4 OnEditRegister</font><font SIZE="3">函数</font><font FACE="Times New Roman" SIZE="3"></p>
<p ALIGN="JUSTIFY">void CRegisterView::OnEditRegister() </p>
<p ALIGN="JUSTIFY">{</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -