📄 chap10.html
字号:
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb_2312-80">
<META NAME="Generator" CONTENT="Microsoft Word 97">
<TITLE>第四章 基于对话框的应用程序</TITLE>
</HEAD>
<BODY>
<FONT FACE="黑体" LANG="ZH-CN" SIZE=5><P ALIGN="CENTER"><A NAME="_Toc425698722">第十章</FONT><FONT FACE="Arial" SIZE=5> MFC</FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=5>通用类</A></P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>不仅提供了大量的用于编写图形用户界面的类,它也包含了许多通用类用于处理字符串、列表、数组、日期和时间,有了这些通用类,编写程序时就可以避免使用复杂的数据结构。例如,由于</FONT><FONT SIZE=3>MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的数组类能够自动的改变大小,我们在不知道数组维数的情况下就不必使用一个大数组,这样就可以节约内存,提高程序的运行速度。</P>
<P ALIGN="JUSTIFY">本章主要涉及以下内容:</P>
<UL>
<P ALIGN="JUSTIFY"><LI>数组类</LI></P>
<P ALIGN="JUSTIFY"><LI>列表类</LI></P>
<P ALIGN="JUSTIFY"><LI>映射类</LI></P>
<P ALIGN="JUSTIFY"><LI>字符串类</LI></P>
<P ALIGN="JUSTIFY"><LI>日期和时间类</LI></P></UL>
</FONT><FONT FACE="仿宋_GB2312" LANG="ZH-CN" SIZE=4><P ALIGN="CENTER"><A NAME="_Toc425698723">第一节</FONT><FONT SIZE=4> </FONT><FONT FACE="仿宋_GB2312" LANG="ZH-CN" SIZE=4>数组类</A></P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的数组类使你可以创建和操作一个实际上可以处理各种数据类型的一维数组对象。除了</FONT><FONT SIZE=3>MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>可以在运行时动态的增大和缩小数组对象外,这些数组对象非常象常规的数组。这也意味者在声明数组对象时不必关心它的维数。由于</FONT><FONT SIZE=3>MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>可以动态的变大和变小,你不必考虑使用常规数组时出现的内存浪费。使用常规数组时你必须将其定义成能够容纳所有可能需要的元素,而不管这些元素是否真的被会使用。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的数组类包含</FONT><FONT SIZE=3>CByteArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>、</FONT><FONT SIZE=3>CDWordArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>、</FONT><FONT SIZE=3>CPtrArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>、</FONT><FONT SIZE=3>CUIntArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>、</FONT><FONT SIZE=3>CWordArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>和</FONT><FONT SIZE=3>CStringArray.</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。从这些类的名称可以看出,每一个类都被设计成能够处理一个特定的数据类型。例如,在本节例子中将要用到的</FONT><FONT SIZE=3>CUIntArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>类是一个处理无符号整形数的数组类,而</FONT><FONT SIZE=3>CObjecArray</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>类代表对象数组类。这些数组类几乎相同,仅仅的区别在于它们储存的数据类型不同。如果你学会使用其中的一种数组类的使用,你就学会了所有数组类的使用。</P>
<P ALIGN="JUSTIFY">数组类有下列成员函数:</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">Add</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">在数组的最后追加一个元素,可以根据需要增大数组大小。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">ElementAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">获得一个指向数组元素的指针</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">FreeExtra</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">释放不用的数组内存</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">GetAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">获取数组内指定位置处的值</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">GetSize</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">获取数组中包含的元素个数</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">GetUpperBound</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">获取数组的上界值。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">InsertAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">在数组的指定位置处插入一个元素,后面的元素的下标加</FONT><FONT SIZE=3>1</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">RemoveAll</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">删除数组中所有的元素。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">SetAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">设定数组指定位置处的值。因为制革函数不会增加数组的大小,故这个下标此时一定要有效。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">SetAtGrow</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">设定数组的指定位置处的值,可以根据需要增大数组的大小。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">SetSize</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()</P>
<P ALIGN="JUSTIFY">设置数组的初始大小。</P>
<P ALIGN="JUSTIFY">下面将介绍一个数组的程序,这个程序可以让你测试一下</FONT><FONT SIZE=3>MFC</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的数组类。</P>
<P ALIGN="JUSTIFY">首先,这个程序在</FONT><FONT SIZE=3>View</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>类中声明一个数组对象,如下:</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">CUIntArray array;</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">接着,在</FONT><FONT SIZE=3>View</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>类的构造函数中初始化数组,将其设置成包含十个元素,</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>array.SetSize(10, 5);</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">SetSize</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数有两个参数,第一个参数是数组的初始大小,第二个参数是数组元素每次增加时增加的个数。</P>
<P ALIGN="JUSTIFY">在设置完数组的大小之后,程序等待用户在窗口中单击鼠标左键或右键。如果用户这样做了,程序将显示一个合适的对话框并且处理输入到对话框中的数据。下面的代码是该程序的</FONT><FONT SIZE=3>OnLButtonDown</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数,用于处理用户单击右键的事件。</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>void CArrayView::OnLButtonDown(UINT nFlags, CPoint point) </P>
<P>{</P>
<P> CArrayAddDlg dialog(this);</P>
<P> dialog.m_index = 0;</P>
<P> dialog.m_value = 0;</P>
<P> dialog.m_radio = 0;</P>
<P> int result = dialog.DoModal();</P>
<P> if (result == IDOK)</P>
<P> {</P>
<P> if (dialog.m_radio == 0)</P>
<P> array.SetAtGrow(dialog.m_index, dialog.m_value);</P>
<P> else if (dialog.m_radio == 1)</P>
<P> array.InsertAt(dialog.m_index, dialog.m_value, 1);</P>
<P> else</P>
<P> </P>
<P>array.Add(dialog.m_value);</P>
<P> Invalidate();</P>
<P> }</P>
<P> CView::OnLButtonDown(nFlags, point);</P>
<P>}</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">这段代码开始先创建一个对话框对象并初始化。如果用户选择对话框的“确定”按钮,</FONT><FONT SIZE=3>OnLButton</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数将检查对话框的成员变量</FONT><FONT SIZE=3>m_radio</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。值为</FONT><FONT SIZE=3>0</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>表示第一个单选按钮(设置)被选中,值为</FONT><FONT SIZE=3>1</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>表示第二个单选按钮(插入)被选中,值为</FONT><FONT SIZE=3>2</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>表示第三个单选按钮(添加)被选中。</P>
<P ALIGN="JUSTIFY">如果用户希望设置数组的元素,程序将调用</FONT><FONT SIZE=3>SetAtGrow</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数,它需要两个参数,一个是数组元素的下标值,另一个是希望设置的值。它不象常规的</FONT><FONT SIZE=3>SetAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数,用户必须使用当前有效的数组下标值。</FONT><FONT SIZE=3>SetAtGrow</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()为了设置指定位置处的值将根据需要增大数组的大小。</P>
<P ALIGN="JUSTIFY">当用户选择了“插入”单选按钮,程序将调用</FONT><FONT SIZE=3>InsertAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数,它需要两个参数,一个是要插入的数组元素的下标,另一个是该数组元素的值。这将在指定位置处创建一个新的数组元素,并将把后面的元素往后推。最后当用户选择了“添加”按钮,程序将调用</FONT><FONT SIZE=3>Add()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>函数,这将在数组的后面添加一个元素。对</FONT><FONT SIZE=3>Invalidate</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()的调用将使程序重新显示数据。</P>
<P ALIGN="JUSTIFY">下面的</FONT><FONT SIZE=3>OnDraw</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数读取并显示数组。</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>void CArrayView::OnDraw(CDC* pDC)</P>
<P>{</P>
<P> CArrayDoc* pDoc = GetDocument();</P>
<P> ASSERT_VALID(pDoc);</P>
<P> // Get the current font's height.</P>
<P> TEXTMETRIC textMetric;</P>
<P> pDC->GetTextMetrics(&textMetric);</P>
<P> int fontHeight = textMetric.tmHeight;</P>
<P> // Get the size of the array. </P>
<P> int count = array.GetSize();</P>
<P> int displayPos = 10;</P>
<P> // Display the array data.</P>
<P> </P>
<P>for (int x=0; x<count; ++x)</P>
<P> {</P>
<P> UINT value = array.GetAt(x);</P>
<P> char s[81];</P>
<P> wsprintf(s, "Element %d contains the value %u.", x, value);</P>
<P> pDC->TextOut(10, displayPos, s);</P>
<P> displayPos += fontHeight;</P>
<P> }</P>
<P>}</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">这里,程序首先获得当前字体的高度,然后程序通过调用</FONT><FONT SIZE=3>GetSize</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数获得数组元素的个数。最后,使用数组元素的个数控制一个</FONT><FONT SIZE=3>for</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>循环,调用</FONT><FONT SIZE=3>GetAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数获得当前下标处的数组元素的值。为了显示程序将数组元素的值转化成字符串。</P>
<P ALIGN="JUSTIFY">程序的</FONT><FONT SIZE=3>OnRButtonDown</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数用来响应用户按下鼠标右键的事件,此函数用来处理删除数组元素的任务。下面是该函数的代码:</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>void CArrayView::OnRButtonDown(UINT nFlags, CPoint point) </P>
<P>{</P>
<P>	// TODO: Add your message handler code here and/or call default</P>
<P> CArrayRemoveDlg dialog(this);</P>
<P> dialog.m_radio= 1;</P>
<P> dialog.m_index= 0;</P>
<P> int result = dialog.DoModal();</P>
<P> if (result == IDOK)</P>
<P> {</P>
<P> if (dialog.m_radio==0)</P>
<P> 		array.RemoveAll();</P>
<P> else</P>
<P> array.RemoveAt(dialog.m_index);</P>
<P> Invalidate();</P>
<P> }</P>
<P>	CView::OnRButtonDown(nFlags, point);</P>
<P>}</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">在这个函数中,当显示完对话框后,程序检查对话框的成员变量</FONT><FONT SIZE=3>m_removeAll</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。如果这个值为真意味着用户希望删除数组中所有的元素。这种情况下,程序调用数组类的成员函数</FONT><FONT SIZE=3>RemoveAll</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()。否则,程序将调用</FONT><FONT SIZE=3>RemoveAt</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()删除指定位置处的数组元素。最后调用</FONT><FONT SIZE=3>Invalidate</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>()函数刷新数据显示。</P>
<P ALIGN="JUSTIFY">下面将介绍对话框类</FONT><FONT SIZE=3>CArrayAddDlg</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,按照下面的步骤创建这个对话框类。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">1.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>创建如图</FONT><FONT SIZE=3>10.1</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>所示的对话框,</FONT><FONT SIZE=3>3</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>个单选按钮的</FONT><FONT SIZE=3>ID</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>分别为</FONT><FONT SIZE=3>IDC_ADD0</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>IDC_ADD1</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>IDC_ADD2</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</P>
<P ALIGN="CENTER"><IMG SRC="Image292.gif" tppabs="http://166.111.167.223/computer/cai/visual_c++_5.0_programming/Image292.gif" WIDTH=247 HEIGHT=154></P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P ALIGN="CENTER">图</FONT><FONT SIZE=1>10. 1 </FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1>添加元素对话框</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">2.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>在</FONT><FONT SIZE=3>ClassWizard</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中为两个文本框映射两个</FONT><FONT SIZE=3>UINT</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>类型的变量</FONT><FONT SIZE=3>m_index</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>m_value</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">3.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>给该对话框添加一个</FONT><FONT SIZE=3>UINT</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>类型的成员变量</FONT><FONT SIZE=3>m_radio</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">4.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>为</FONT><FONT SIZE=3>WM_INITDIALOG</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>添加函数</FONT><FONT SIZE=3>OnInitDialog()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,在其中设置单选按钮的初始状态。</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>BOOL CArrayAddDlg::OnInitDialog() </P>
<P>{</P>
<P>	CDialog::OnInitDialog();</P>
<P>	</P>
<P>	// TODO: Add extra initialization here</P>
<P>	((CButton*)GetDlgItem(IDC_ADD0))->SetCheck(1);</P>
<P>	return TRUE; // return TRUE unless you set the focus to a control</P>
<P>	 // EXCEPTION: OCX Property Pages should return FALSE</P>
<P>}</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -