📄 chap5_3.htm
字号:
</tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_INCOME</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">CListBox</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_ctrlIncome</span></td> </tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_KIND</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">CString</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strKind</span></td> </tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_MARRIED</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">BOOL</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_bMarried</span></td> </tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_NAME</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">CString</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strName</span></td> </tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_SEX</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">int</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_nSex</span></td> </tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_UNIT</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">CString</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strUnit</span></td> </tr> <tr> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">IDC_WORK</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">int</span></td> <td WIDTH="33%"><p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_nWork</span></td> </tr> </table> <p><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">读者会注意到控件IDC_INCOME居然有两个变量,一个是CString型的,一个是CListBox型的,这是完全合法的,不会引起任何冲突。之所以要加入CListBox型的变量,是因为列表框的初始化要通过CListBox对象进行。</span></p> <div align="center"><center><table border="2" cellpadding="2" cellspacing="0" width="90%" bgcolor="#A6C0F0"> <tr> <td width="100%"><span style="font-size: 9pt">提示:在ClassWizard中可分别为一个控件指定一个数据变量和一个控件对象,这样做的好处是即能方便地获得数据,又能方便地控制控件。</span></td> </tr> </table> </center></div><p ALIGN="JUSTIFY"><span style="font-size: 9pt"><font color="#3973DE">5.3.3对话框的初始化</font></span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">对话框的初始化工作一般在构造函数和OnInitDialog函数中完成。在构造函数中的初始化主要是针对对话框的数据成员。读者可以找到CRegisterDialog的构造函数,如清单5.1所示。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">清单5.1 CRegisterDialog的构造函数</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">CRegisterDialog::CRegisterDialog(CWnd* pParent /*=NULL*/)</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">: CDialog(CRegisterDialog::IDD, pParent)</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">{</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">//{{AFX_DATA_INIT(CRegisterDialog)</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_nAge = 0;</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strIncome = _T("");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strKind = _T("");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_bMarried = FALSE;</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strName = _T("");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_nSex = -1;</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_strUnit = _T("");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_nWork = -1;</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">//}}AFX_DATA_INIT</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">}</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">可以看出,对数据成员的初始化是由ClassWizard自动完成的。若读者对初值的含义还不太清楚,请参看表5.3。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">在对话框创建时,会收到WM_INITDIALOG消息,对话框对该消息的处理函数是OnInitDialog。调用OnInitDialog时,对话框已初步创建,对话框的窗口句柄也已有效,但对话框还未被显示出来。因此,可以在OnInitDialog中做一些影响对话框外观的初始化工作。OnInitDialog对对话框的作用与OnCreate对CMainFrame的作用类似。</span></p> <div align="center"><center><table border="2" cellpadding="2" cellspacing="0" width="90%" bgcolor="#A6C0F0"> <tr> <td width="100%"><span style="font-size: 9pt">提示:MFC窗口的初始化工作一般在OnCreate成员函数中进行,但对话框的初始化工作最好在OnInitDialog中进行。</span></td> </tr> </table> </center></div><p ALIGN="JUSTIFY"><span style="font-size: 9pt">OnInitDialog是WM_INITDIALOG消息的处理函数,所以要用ClassWizard为RegisteritDialog类增加一个WM_INITDIALOG消息的处理函数,增加的方法是进入ClassWizard后,先选中MessageMaps标签,然后在Class name中选择CRegisterDialog,在Object IDs栏中选择CRegisterDialog,在Messages栏中找到WM_INITDIALOG并双击之,最后按OK按钮退出ClassWizard。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">请读者按清单5.2修改OnInitDialog函数。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">清单5.2 OnInitDialog函数</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">BOOL CRegisterDialog::OnInitDialog() </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">{</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">CDialog::OnInitDialog();</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">// TODO: Add extra initialization here</span></p> <p><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_ctrlIncome.AddString("500元以下");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_ctrlIncome.AddString("500-1000元");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_ctrlIncome.AddString("1000-2000元");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">m_ctrlIncome.AddString("2000元以上");</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">return TRUE; // return TRUE unless you set the focus to a control</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">// EXCEPTION: OCX Property Pages should return FALSE</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">}</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">CRegisterDialog::OnInitDialog()的主要任务是对工资收入列表框的列表项进行初始化。调用CListBox::AddString可将指定的字符串加入到列表框中。由于该列表是不自动排序的,因此AddString将表项加在列表框的末尾。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"><font color="#3973DE">5.3.4对话框的数据交换机制</font></span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">对话框的数据成员变量存储了与控件相对应的数据。数据变量需要和控件交换数据,以完成输入或输出功能。例如,一个编辑框即可以用来输入,也可以用来输出:用作输入时,用户在其中输入了字符后,对应的数据成员应该更新;用作输出时,应及时刷新编辑框的内容以反映相应数据成员的变化。对话框需要一种机制来实现这种数据交换功能,这对对话框来说是至关重要的。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">MFC提供了类CDataExchange来实现对话框类与控件之间的数据交换(DDX),该类还提供了数据有效机制(DDV)。数据交换和数据有效机制适用于编辑框、检查框、单选按钮、列表框和组合框。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">数据交换的工作由CDialog::DoDataExchange来完成。读者可以找到CRegisterDialog::DoDataExchange函数,如清单5.3所示。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt"> </span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">清单5.3 DoDataExchange函数</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">void CRegisterDialog::DoDataExchange(CDataExchange* pDX)</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">{</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">CDialog::DoDataExchange(pDX);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">//{{AFX_DATA_MAP(CRegisterDialog)</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Control(pDX, IDC_INCOME, m_ctrlIncome);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_LBString(pDX, IDC_INCOME, m_strIncome);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_CBString(pDX, IDC_KIND, m_strKind);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Check(pDX, IDC_MARRIED, m_bMarried);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Text(pDX, IDC_NAME, m_strName);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Radio(pDX, IDC_SEX, m_nSex);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Text(pDX, IDC_UNIT, m_strUnit);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Radio(pDX, IDC_WORK, m_nWork);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDX_Text(pDX, IDC_AGE, m_nAge);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">DDV_MinMaxUInt(pDX, m_nAge, 16, 65);</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">//}}AFX_DATA_MAP</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">}</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">读者可以看出,该函数中的代码是由ClassWizard自动加入的。DoDataExchange只有一个参数,即一个CDataExchange对象的指针pDX。在该函数中调用了DDX函数来完成数据交换,调用DDV函数来进行数据有效检查。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">当程序需要交换数据时,不要直接调用DoDataExchange函数,而应该调用CWnd::UpdateData。UpdataData函数内部调用了DoDataExchange。该函数只有一个布尔型参数,它决定了数据传送的方向。调用UpdateData(TRUE)将数据从对话框的控件中传送到对应的数据成员中,调用UpdateData(FALSE)则将数据从数据成员中传送给对应的控件。</span></p> <p ALIGN="JUSTIFY"><span style="font-size: 9pt">在缺省的CDialog::OnInitDialog中调用了UpdateData(FALSE),这样,在对话框创建时,数据成员的初值就会反映到相应的控件上。若用户是按了OK(确定)按钮退出对话框,则对话框认为输入有效,就会调用UpdataData(TRUE)将控件中的数据传给数据成员。图5.9描绘了对话框的这种数据交换机制。</span></p> <p ALIGN="CENTER"><span style="font-size: 9pt"><img src="T5_9.gif"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -