QQ登录

只需要一步,快速开始

 注册地址  找回密码
12
返回列表 发新帖
楼主: 韩冰
打印 上一主题 下一主题

BCB教程

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

11#
发表于 2005-1-26 01:22 |只看该作者
|招呼Ta 关注Ta
<b><FONT face=宋体 size=6> </FONT></b>< align=center>使用媒体播放器控件</P><FONT face=宋体 size=3>< align=justify>上一讲中我们学习了利用文件来保存记录以及从文件中读取记录的方法,想必读者朋友们已经动手实践过了。其实,心铃在上一讲中给出的源代码中留下了一个隐藏的问题,不知道是否有朋友发现了?这个问题是:按照目前的代码,当我们利用查询功能查询出部分记录后,再添加一个新的记录,就会发现文件中原有的部分记录(当前未显示的记录)丢失了。第七讲曾经介绍过,编程错误通常可分为语法错误、运行时错误和逻辑错误三种类型,逻辑错误往往会引起程序功能上的问题,同时也不容易发现,上一讲留下的问题就属于一种逻辑错误,究其原因,是因为我们暂时用</FONT><FONT face="宋体, MS Song" size=3>ListView</FONT><FONT face=宋体 size=3>控件来管理记录集,当查询功能执行后,</FONT><FONT face="宋体, MS Song" size=3>ListView</FONT><FONT face=宋体 size=3>控件中的记录数量就减少了,此后再执行添加功能时,</FONT><FONT face="宋体, MS Song" size=3>BtnAddSongClick</FONT><FONT face=宋体 size=3>调用</FONT><FONT face="宋体, MS Song" size=3>SaveFile</FONT><FONT face=宋体 size=3>只会把</FONT><FONT face="宋体, MS Song" size=3>ListView</FONT><FONT face=宋体 size=3>控件中的记录保存在文件中,从而造成记录丢失。</P>< align=justify>为了解决这一问题,可以在执行添加操作时先从文件中读取所有记录,然后再写回去,或者用一个专门的数据链表来管理记录集,这两种方法的具体实现就作为练习留给读者朋友自己来完成,在后面的讲座中,我们将改用数据库来管理记录集,从而解决上述问题。在本讲中,我们将要学习使用媒体播放器控件来播放</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>歌曲的方法。</P><UL><B>< align=justify><LI>媒体播放器控件简介   ]) s" v1 M& x; W4 R6 ?$ K6 @
</LI></UL></B></FONT><FONT size=3>< align=justify>CBuilder</FONT><FONT face=宋体 size=3>的媒体播放器控件是能够播放音频、视频等多种多媒体文件的控件,它的</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>封装类为</FONT><FONT size=3>TMediaPlayer</FONT><FONT face=宋体 size=3>。媒体播放器控件的工作原理是通过</FONT><FONT size=3>Windows</FONT><FONT face=宋体 size=3>的</FONT><FONT size=3>MCI</FONT><FONT face=宋体 size=3>接口来控制多媒体播放设备,它支持的媒体数据种类很多,如</FONT><FONT size=3>WAV</FONT><FONT face=宋体 size=3>文件、</FONT><FONT size=3>AVI</FONT><FONT face=宋体 size=3>文件、</FONT><FONT size=3>CD-ROM</FONT><FONT face=宋体 size=3>音乐、</FONT><FONT size=3>MIDI</FONT><FONT face=宋体 size=3>音乐,以及</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>音乐等等。</P>< align=justify>媒体播放器控件(图</FONT><FONT face="宋体, MS Song" size=3>11-1</FONT><FONT face=宋体 size=3>)由一系列按钮组成,其中包括:播放(</FONT><FONT face="宋体, MS Song" size=3>lay</FONT><FONT face=宋体 size=3>)、暂停(</FONT><FONT face="宋体, MS Song" size=3>ause</FONT><FONT face=宋体 size=3>)、停止(</FONT><FONT face="宋体, MS Song" size=3>Stop</FONT><FONT face=宋体 size=3>)、下一首(</FONT><FONT face="宋体, MS Song" size=3>Next</FONT><FONT face=宋体 size=3>)、前一首(</FONT><FONT face="宋体, MS Song" size=3>rev</FONT><FONT face=宋体 size=3>)、前进(</FONT><FONT face="宋体, MS Song" size=3>Step</FONT><FONT face=宋体 size=3>)、后退(</FONT><FONT face="宋体, MS Song" size=3>Back</FONT><FONT face=宋体 size=3>)、录制(</FONT><FONT face="宋体, MS Song" size=3>Record</FONT><FONT face=宋体 size=3>)、弹出(</FONT><FONT face="宋体, MS Song" size=3>Eject</FONT><FONT face=宋体 size=3>)等,用户可以通过这些按钮来控制媒体播放器的播放操作。</P>< align=justify>媒体播放器控件最主要的属性是</FONT><FONT face="宋体, MS Song" size=3>DeviceType</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>,其中</FONT><FONT face="宋体, MS Song" size=3>DeviceType</FONT><FONT face=宋体 size=3>指定要操作的媒体设备类型,这里的媒体设备可以是硬件设备也可以是软件驱动设备,例如</FONT><FONT face="宋体, MS Song" size=3>dtCDAudio</FONT><FONT face=宋体 size=3>表示</FONT><FONT face="宋体, MS Song" size=3>CD-ROM</FONT><FONT face=宋体 size=3>音乐播放设备,</FONT><FONT face="宋体, MS Song" size=3>dtVCR</FONT><FONT face=宋体 size=3>表示</FONT><FONT face="宋体, MS Song" size=3>WAV</FONT><FONT face=宋体 size=3>播放设备,如果不能确定媒体设备的类型,则可以设置此属性为</FONT><FONT face="宋体, MS Song" size=3>dtAutoSelect</FONT><FONT face=宋体 size=3>,媒体播放控件就会根据</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>属性的文件类型来自动选择合适的播放设备。</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>AnsiString</FONT><FONT face=宋体 size=3>类型的字符串,用来指定播放或录制的媒体文件名称。</P>< align=justify>设置了媒体播放器控件的</FONT><FONT face="宋体, MS Song" size=3>DeviceType</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>属性后,还需要打开该媒体设备,才能进行播放等操作。当媒体播放器控件的</FONT><FONT face="宋体, MS Song" size=3>AutoOpen</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>时,媒体设备会自动打开,该属性为</FONT><FONT face="宋体, MS Song" size=3>false</FONT><FONT face=宋体 size=3>时,程序中必须通过控件的</FONT><FONT face="宋体, MS Song" size=3>Open()</FONT><FONT face=宋体 size=3>方法来打开媒体播放设备。</P>< align=justify>如果打开媒体设备正确,用户就可以通过控件上的按钮进行播放、停止、前进、后退等操作,程序中也可以通过调用控件的方法,例如</FONT><FONT face="宋体, MS Song" size=3>lay()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Stop()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Step()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Back()</FONT><FONT face=宋体 size=3>等进行相同的操作。对于不同的媒体类型,用户可以进行的操作是不同的,例如,对</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐文件来说,录音、弹出等操作是无效的;即使对同一个媒体文件,在不同的状态下可进行的操作也不相同。如果设置媒体播放器控件的</FONT><FONT face="宋体, MS Song" size=3>AutoEnable</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,则控件可以自己管理其上的</FONT><FONT face="宋体, MS Song" size=3>9</FONT><FONT face=宋体 size=3>个按钮是有效还是失效状态,如果该属性为</FONT><FONT face="宋体, MS Song" size=3>false</FONT><FONT face=宋体 size=3>,则程序中可以通过设置控件的</FONT><FONT face="宋体, MS Song" size=3>EnableButtons</FONT><FONT face=宋体 size=3>属性来决定哪些按钮有效。</P>< align=justify>媒体播放器控件既可以播放音频数据,也可以播放视频数据。如果播放的媒体文件中包含视频信息,则可以设置控件的</FONT><FONT face="宋体, MS Song" size=3>Display</FONT><FONT face=宋体 size=3>属性,作为视频信息的输出窗口。如果将</FONT><FONT face="宋体, MS Song" size=3>Display</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>NULL</FONT><FONT face=宋体 size=3>,则控件在播放视频文件时,会自动创建一个窗口用于视频输出。</P>< align=justify>上面简要介绍了媒体播放器控件的主要功能及其基本使用方法,下面我们就来学习如何在</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>中使用媒体播放器控件。</P><UL><B>< align=justify><LI>设置属性 <p></LI></UL></B>< align=justify>使用媒体播放器控件之前,应该在编辑状态下设置好它的各项属性。首先设置控件的媒体类型属性</FONT><FONT face="宋体, MS Song" size=3>DeviceType</FONT><FONT face=宋体 size=3>为</FONT><FONT face="宋体, MS Song" size=3>dtAutoSelect</FONT><FONT face=宋体 size=3>,媒体播放器控件在</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>中主要用于播放</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件,由于</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件格式较新,帮助文档中没有给出</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>专用的媒体属性值,因此将</FONT><FONT face="宋体, MS Song" size=3>DeviceType</FONT><FONT face=宋体 size=3>设为</FONT><FONT face="宋体, MS Song" size=3>dtAutoSelect</FONT><FONT face=宋体 size=3>,只要是媒体播放器控件支持的,并且系统中又安装了相应驱动程序的媒体类型都可以适用。</P>< align=justify>由于</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件名称需要在运行时根据用户的选择进行设定,因此我们在编辑时把媒体播放器控件的另一个重要属性</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>设为空。媒体播放器控件是一个自动化程度较高的控件,可以设置其</FONT><FONT face="宋体, MS Song" size=3>AutoEnable</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,让它在运行时自动响应用户的操作,自动管理各个按钮是否为有效状态。另外,设置控件的</FONT><FONT face="宋体, MS Song" size=3>AutoOpen</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>false</FONT><FONT face=宋体 size=3>,取消其自动打开媒体设备的功能,由程序控制媒体设备的打开操作;并设置控件的</FONT><FONT face="宋体, MS Song" size=3>AutoRewind</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,使一个</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件播放完毕后可以自动回到文件头的位置。除此之外,其余的属性接受缺省值即可。</P><UL><B>< align=justify><LI>实现简单播放功能 <p></LI></UL></B>< align=justify>当用户在列表框中选中某一首</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐时,让媒体播放器控件打开该文件,如果打开成功,则控件上的相应按钮自动变为有效的状态,用户可以通过操作控件上的按钮,播放该</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐。这是最简单的播放功能的实现方法。在第九讲中曾介绍过显示当前选中记录的实现方法,我们就在此基础上,将当前选中记录的</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件名赋给媒体播放器控件的</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>属性,并调用其</FONT><FONT face="宋体, MS Song" size=3>Open()</FONT><FONT face=宋体 size=3>方法打开该文件,实现简单播放功能。另外,为了便于后面实现向前向后浏览和循环播放等功能,我们在</FONT><FONT face="宋体, MS Song" size=3>TMainForm</FONT><FONT face=宋体 size=3>类中添加成员变量</FONT><FONT face="宋体, MS Song" size=3>int m_CurPlayIndex</FONT><FONT face=宋体 size=3>,用于记录当前播放的文件序号,即当前播放的</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>记录在</FONT><FONT face="宋体, MS Song" size=3>ListView1</FONT><FONT face=宋体 size=3>控件列表中的序号。打开当前选中的</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件的代码如下所示:</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm:istView1SelectItem(TObject *Sender, TListItem *Item, bool Selected)</P>< align=justify>{</P>< align=justify>if(Item)</P>< align=justify>{</P><DIR>< align=justify>//</FONT><FONT face=宋体 size=3>将当前选中列表项的内容写入编辑框中</P><DIR>< align=justify>……(略)</P></DIR></FONT><FONT size=3>< align=justify>m_CurPlayIndex=Item-&gt;Index; //</FONT><FONT face=宋体 size=3>当前播放的文件序号为</FONT><FONT size=3>ListView1</FONT><FONT face=宋体 size=3>控件中的列表序号</P></FONT><FONT size=3>< align=justify>//</FONT><FONT face=宋体 size=3>把记录的文件名赋给媒体播放控件的</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>属性</P></FONT><FONT size=3>< align=justify>MediaPlayer1-&gt;FileName=edtFileName-&gt;Text;</P>< align=justify>MediaPlayer1-&gt;Open();//</FONT><FONT face=宋体 size=3>打开该</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件</P></DIR><P align=justify>}</P><P align=justify>}</P><UL><B><P align=justify><LI>实现向前、向后浏览功能 <p></LI></UL></B><P align=justify>接下来我们要实现向前向后浏览功能,即当用户点击媒体播放器控件的</FONT><FONT face="宋体, MS Song" size=3>Prev</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Next</FONT><FONT face=宋体 size=3>按钮时,程序可以在</FONT><FONT face="宋体, MS Song" size=3>ListView1</FONT><FONT face=宋体 size=3>中向前或向后浏览并播放相应的</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件。为了实现这一功能,我们需要处理用户点击媒体播放器按钮时所产生的</FONT><FONT face="宋体, MS Song" size=3>OnClick</FONT><FONT face=宋体 size=3>事件。通过对象浏览器添加该事件的处理函数</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>,该函数的实现代码在下一小节中给出,这里先介绍一下它的编程思路。</P><P align=justify>事件处理函数</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>有一个</FONT><FONT face="宋体, MS Song" size=3>TMPBtnType Button</FONT><FONT face=宋体 size=3>参数,它指出了用户点击的是哪一个按钮。当我们判断出用户点击了</FONT><FONT face="宋体, MS Song" size=3>Next</FONT><FONT face=宋体 size=3>按钮时,就让</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>加一,如果</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>的值超过了列表框控件中的记录总数,则让</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>等于</FONT><FONT face="宋体, MS Song" size=3>0</FONT><FONT face=宋体 size=3>。同样,当用户点击</FONT><FONT face="宋体, MS Song" size=3>Prev</FONT><FONT face=宋体 size=3>按钮时,就让</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>减一,如果</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>小于</FONT><FONT face="宋体, MS Song" size=3>0</FONT><FONT face=宋体 size=3>,则让</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>回到记录的尾部。</P><P align=justify>调整好</FONT><FONT face="宋体, MS Song" size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>的值以后,我们再将其对应的</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件名赋给媒体播放器控件的</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>属性,并调用控件的</FONT><FONT face="宋体, MS Song" size=3>Open()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Play()</FONT><FONT face=宋体 size=3>方法来打开并播放该文件,这些播放操作统一在成员函数</FONT><FONT face="宋体, MS Song" size=3>PlayTheSong()</FONT><FONT face=宋体 size=3>中完成,其实现如下:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm:layTheSong()</P></FONT><FONT face=宋体 size=3><P align=justify>{</P></FONT><FONT size=3><P align=justify>TListItem *theItem;</P><P align=justify>theItem=ListView1-&gt;Items-&gt;Item[m_CurPlayIndex];//</FONT><FONT face=宋体 size=3>获取</FONT><FONT size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>对应的列表项</P></FONT><FONT size=3><P align=justify>edtFileName-&gt;Text=theItem-&gt;Caption;</P><P align=justify>edtSongName-&gt;Text=theItem-&gt;SubItems-&gt;Strings[0];</P><P align=justify>edtSingerName-&gt;Text=theItem-&gt;SubItems-&gt;Strings[1];</P><P align=justify>ListView1-&gt;Selected =theItem;//</FONT><FONT face=宋体 size=3>将</FONT><FONT size=3>m_CurPlayIndex</FONT><FONT face=宋体 size=3>对应的列表项设为当前选中项</P></FONT><FONT size=3><P align=justify>MediaPlayer1-&gt;FileName=theItem-&gt;Caption;</P><P align=justify>MediaPlayer1-&gt;Open();</P><P align=justify>MediaPlayer1-&gt;Play();</P></FONT><FONT face=宋体 size=3><P align=justify>}</P><UL><B><P align=justify><LI>实现循环播放功能 <p></LI></UL></B><P align=justify>循环播放是指当一个</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件播放完毕后,媒体播放器控件自动跳到下一个</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件,如此循环,直到用户按下</FONT><FONT face="宋体, MS Song" size=3>Stop</FONT><FONT face=宋体 size=3>按钮停止播放为止。</P><P align=justify>实现该功能的关键是怎样判断什么时候一个</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件已播放完毕,心铃准备使用定时查询的方法来检测是否播放到了</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件的尾部。定时查询的方法需要添加一个时钟控件</FONT><FONT face="宋体, MS Song" size=3>Timer1</FONT><FONT face=宋体 size=3>,该控件位于</FONT><FONT face="宋体, MS Song" size=3>System</FONT><FONT face=宋体 size=3>元件栏中,</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>类为</FONT><FONT face="宋体, MS Song" size=3>TTimer</FONT><FONT face=宋体 size=3>。</FONT><FONT face="宋体, MS Song" size=3>Timer1</FONT><FONT face=宋体 size=3>控件在运行时是不可见的,但每隔一定的时间间隔便会产生定时事件</FONT><FONT face="宋体, MS Song" size=3>OnTimer</FONT><FONT face=宋体 size=3>。我们把</FONT><FONT face="宋体, MS Song" size=3>Timer1</FONT><FONT face=宋体 size=3>控件的时间间隔属性</FONT><FONT face="宋体, MS Song" size=3>Interval</FONT><FONT face=宋体 size=3>设为</FONT><FONT face="宋体, MS Song" size=3>200</FONT><FONT face=宋体 size=3>毫秒,</FONT><FONT face="宋体, MS Song" size=3>Enabled</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>false</FONT><FONT face=宋体 size=3>,并添加定时事件处理函数</FONT><FONT face="宋体, MS Song" size=3>Timer1Timer()</FONT><FONT face=宋体 size=3>。</P><P align=justify>在</FONT><FONT face="宋体, MS Song" size=3>Timer1Timer()</FONT><FONT face=宋体 size=3>中,程序首先检查媒体播放器控件当前播放的位置</FONT><FONT face="宋体, MS Song" size=3>Position</FONT><FONT face=宋体 size=3>,将其与</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐的长度相比较,如果二者相等,则表示已经播放到了文件尾。再检测循环选项按钮</FONT><FONT face="宋体, MS Song" size=3>chkLoop</FONT><FONT face=宋体 size=3>是否处于选中状态,以及媒体播放器是否处于播放状态,如果这两个条件均符合,就打开并播放列表框中的下一个</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件;否则表示播放结束,关闭时钟。事件处理函数</FONT><FONT face="宋体, MS Song" size=3>Timer1Timer()</FONT><FONT face=宋体 size=3>如下所示。</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::Timer1Timer(TObject *Sender)</P><P align=justify>{</P><P align=justify>if(MediaPlayer1-&gt;Position == MediaPlayer1-&gt;Length)</P></FONT><FONT face=宋体 size=3><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>检测</FONT><FONT size=3>chkLoop</FONT><FONT face=宋体 size=3>是否处于选中状态,以及媒体播放器是否处于播放状态</P></FONT><FONT size=3><P align=justify>if(chkLoop-&gt;Checked &amp;&amp; m_bIsPlaying) //</FONT><FONT face=宋体 size=3>如果条件符合,则计算下一个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>记录序号</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>if(m_CurPlayIndex&lt;ListView1-&gt;Items-&gt;Count-1) m_CurPlayIndex++;</P><P align=justify>else m_CurPlayIndex=0;</P><P align=justify>PlayTheSong();//</FONT><FONT face=宋体 size=3>打开并播放该</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>else</P></FONT><FONT face=宋体 size=3><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(true);//</FONT><FONT face=宋体 size=3>使记录操作按钮有效</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled =false;//</FONT><FONT face=宋体 size=3>关闭时钟</P></DIR><P align=justify>}</P></DIR><P align=justify>}</P><P align=justify>}</P><P align=justify>其中,</FONT><FONT face="宋体, MS Song" size=3>EnableButtons()</FONT><FONT face=宋体 size=3>用来设置“添加”、“删除”、“修改”等记录操作按钮的状态。当媒体播放器控件正在播放时,为了避免因用户操作引起冲突,最好让这些记录操作按钮为无效状态,播放完毕后,再让它们有效。</FONT><FONT face="宋体, MS Song" size=3>EnableButtons()</FONT><FONT face=宋体 size=3>函数如下所示:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::EnableButtons(bool bEnable)</P><P align=justify>{</P><P align=justify>btnAdd-&gt;Enabled=bEnable;</P><P align=justify>btnDelete-&gt;Enabled=bEnable;</P><P align=justify>btnModify-&gt;Enabled=bEnable;</P><P align=justify>btnFind-&gt;Enabled =bEnable;</P><P align=justify>btnShowAll-&gt;Enabled=bEnable;</P></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>Timer1</FONT><FONT face=宋体 size=3>控件的初始状态是无效的,只有在播放期间是有效的。播放期间起始于用户按下</FONT><FONT size=3>Play</FONT><FONT face=宋体 size=3>按钮时,终止于用户按下</FONT><FONT size=3>Stop</FONT><FONT face=宋体 size=3>按钮,因此我们要在事件处理函数</FONT><FONT size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>中处理</FONT><FONT size=3>Play</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>Stop</FONT><FONT face=宋体 size=3>按钮的点击事件,分别打开和关闭</FONT><FONT size=3>Timer1</FONT><FONT face=宋体 size=3>。另外,我们还要在</FONT><FONT size=3>TMainForm</FONT><FONT face=宋体 size=3>类中添加了一个成员变量</FONT><FONT size=3>bool m_bIsPlaying</FONT><FONT face=宋体 size=3>,用来表示当前媒体播放器是否处于播放状态,设置和清除</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>的操作也都在</FONT><FONT size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>中完成。下面就是</FONT><FONT size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>的实现代码:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::MediaPlayer1Click(TObject *Sender,TMPBtnType Button,bool &amp;DoDefault)</P><P align=justify>{</P><P align=justify>switch(Button) //</FONT><FONT face=宋体 size=3>根据</FONT><FONT size=3>Button</FONT><FONT face=宋体 size=3>参数判断用户点击了什么按钮</P><P align=justify>{</P></FONT><FONT size=3><P align=justify>case btPlay: //</FONT><FONT face=宋体 size=3>如果为</FONT><FONT size=3>Play</FONT><FONT face=宋体 size=3>按钮,设置</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>标志、打开时钟、使记录操作按钮失效</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(false); //</FONT><FONT face=宋体 size=3>使记录操作按钮失效</P></FONT><FONT size=3><P align=justify>m_bIsPlaying=true; //</FONT><FONT face=宋体 size=3>设置</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>标志</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled=true;//</FONT><FONT face=宋体 size=3>打开时钟</P></FONT><FONT size=3><P align=justify>break;</P></DIR><P align=justify>case btStop: //</FONT><FONT face=宋体 size=3>如果为</FONT><FONT size=3>Stop</FONT><FONT face=宋体 size=3>按钮,清除</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>标志、关闭时钟、使记录操作按钮有效</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(true); //</FONT><FONT face=宋体 size=3>使记录操作按钮有效</P></FONT><FONT size=3><P align=justify>m_bIsPlaying=false; //</FONT><FONT face=宋体 size=3>清除</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>标志</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled=false; //</FONT><FONT face=宋体 size=3>关闭时钟</P></FONT><FONT size=3><P align=justify>break;</P></DIR><P align=justify>case Mplayer::btNext: //</FONT><FONT face=宋体 size=3>如果为</FONT><FONT size=3>Next</FONT><FONT face=宋体 size=3>按钮,播放下一个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(false);</P><P align=justify>//</FONT><FONT face=宋体 size=3>计算下一个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件的记录序号</P></FONT><FONT size=3><P align=justify>if(m_CurPlayIndex&lt;ListView1-&gt;Items-&gt;Count-1) m_CurPlayIndex++;</P><P align=justify>else m_CurPlayIndex=0;</P><P align=justify>m_bIsPlaying=true;</P><P align=justify>DoDefault=false; //</FONT><FONT face=宋体 size=3>不执行缺省的按钮事件</P></FONT><FONT size=3><P align=justify>PlayTheSong();//</FONT><FONT face=宋体 size=3>执行打开和播放</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件等操作</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled=true; </P><P align=justify>break;</P></DIR><P align=justify>case Mplayer::btPrev: //</FONT><FONT face=宋体 size=3>如果为</FONT><FONT size=3>Next</FONT><FONT face=宋体 size=3>按钮,播放前一个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(false);</P><P align=justify>//</FONT><FONT face=宋体 size=3>计算前一个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件的记录序号</P></FONT><FONT size=3><P align=justify>if(m_CurPlayIndex&gt;0) m_CurPlayIndex--;</P><P align=justify>else m_CurPlayIndex=ListView1-&gt;Items-&gt;Count-1;</P><P align=justify>m_bIsPlaying=true;</P><DIR><P align=justify>DoDefault=false;</P></DIR><P align=justify>PlayTheSong();</P><P align=justify>Timer1-&gt;Enabled=true;</P><P align=justify>break;</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P><B><P align=justify> </P></B><P align=justify>本讲中我们学习了如何使用媒体播放器控件来播放</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐,到目前为至,</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>程序的大部分功能都已经实现了,下一讲中我们要为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>添加一些辅助功能,并学习有关界面设计更多的知识。另外,下一讲结束之后,心铃会把</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>第一阶段的源程序以及讲座的部分电子文档放在主页上供朋友们下载,至于网址嘛,请看下回分解。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>进一步完善应用程序</P><FONT face=宋体 size=3>< align=justify>到上一讲为至,</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>程序已经具有了记录、编辑、存取文件、查找记录、播放</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐等功能,基本上达到了我们的设计目标,但就操作方便程度而言,</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>还有所欠缺,因此在本讲中,我们就来为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>添加一些辅助功能,使之更加完善。</P><UL><B>< align=justify><LI>实现排序功能 8 J' W# H" G* q# S3 C
</LI></UL></B>< align=justify>为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>添加排序功能之后,用户只要用鼠标点击记录列表框的某一列标题头,就可以以该项内容为基础按照字母排列顺序对记录进行排序,如果用户连续两次点击同一列,则可以在升序排列和降序排列之间切换。要实现这个功能,首先需要响应列表框的标题点击事件</FONT><FONT face="宋体, MS Song" size=3>OnColumnClick</FONT><FONT face=宋体 size=3>,在该事件处理函数中判断是哪一列的标题头被点击,并利用列表框控件的</FONT><FONT face="宋体, MS Song" size=3>AlphaSort()</FONT><FONT face=宋体 size=3>方法对列表框中的记录进行排序。</P></FONT><FONT size=3>< align=justify>AlphaSort()</FONT><FONT face=宋体 size=3>方法可以依据两种标准来进行排序,一是根据列表框控件的</FONT><FONT size=3>SortType</FONT><FONT face=宋体 size=3>属性,该属性支持按照列表项的</FONT><FONT size=3>Caption</FONT><FONT face=宋体 size=3>属性以及</FONT><FONT size=3>Data</FONT><FONT face=宋体 size=3>属性进行排序,而本程序中需要实现对任意一个子列进行排序,不能通过简单地设置</FONT><FONT size=3>SortType</FONT><FONT face=宋体 size=3>属性来实现,因此我们采用第二种方法,即为列表框控件添加</FONT><FONT size=3>OnCompare</FONT><FONT face=宋体 size=3>事件处理函数。添加了</FONT><FONT size=3>OnCompare</FONT><FONT face=宋体 size=3>事件处理函数之后,列表框控件在排序时会自动调用该函数来比较两个列表项的次序,并根据</FONT><FONT size=3>OnCompare</FONT><FONT face=宋体 size=3>返回的结果进行排序。</P>< align=justify>下面就是</FONT><FONT face="宋体, MS Song" size=3>ListView1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>OnColumnClick</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>OnCompare</FONT><FONT face=宋体 size=3>两个事件的处理函数:</P></FONT><FONT size=3>< align=justify>//ListView1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>OnCompare</FONT><FONT face=宋体 size=3>事件处理函数,其中参数</FONT><FONT size=3>Item1</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>Item2</FONT><FONT face=宋体 size=3>是进行比较的列表项,</P></FONT><FONT size=3>< align=justify>//</FONT><FONT face=宋体 size=3>通过参数</FONT><FONT size=3>Compare</FONT><FONT face=宋体 size=3>返回比较的结果。</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm:istView1Compare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &amp;Compare)</P>< align=justify>{</P>< align=justify>if (ColumnToSort == 0)//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>ColumnToSort</FONT><FONT face=宋体 size=3>为</FONT><FONT size=3>0</FONT><FONT face=宋体 size=3>,则按列表项</FONT><FONT size=3>Caption</FONT><FONT face=宋体 size=3>属性进行比较</P><DIR></FONT><FONT size=3>< align=justify>Compare = CompareText(Item1-&gt;Caption,Item2-&gt;Caption);</P></DIR>< align=justify>else //</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>ColumnToSort</FONT><FONT face=宋体 size=3>不为</FONT><FONT size=3>0</FONT><FONT face=宋体 size=3>,计算子列的序号,并按子列项进行比较</P>< align=justify>{</P><DIR></FONT><FONT size=3>< align=justify>int ix = ColumnToSort-1;</P>< align=justify>Compare = CompareText(Item1-&gt;SubItems-&gt;Strings[ix], Item2-&gt;SubItems-&gt;Strings[ix]);</P></DIR></FONT><FONT face=宋体 size=3>< align=justify>}</P></FONT><FONT size=3>< align=justify>//Tag</FONT><FONT face=宋体 size=3>属性为</FONT><FONT size=3>1</FONT><FONT face=宋体 size=3>时升序排列,为</FONT><FONT size=3>0</FONT><FONT face=宋体 size=3>时降序排列</P></FONT><FONT size=3>< align=justify>if(ListView1-&gt;Columns-&gt;Items[ColumnToSort]-&gt;Tag) Compare = -Compare;</P></FONT><FONT face=宋体 size=3>< align=justify>}</P></FONT><FONT size=3>< align=justify>//ListView1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>OnColumnClick</FONT><FONT face=宋体 size=3>事件处理函数</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm:istView1ColumnClick(TObject *Sender, TListColumn *Column)</P>< align=justify>{</P>< align=justify>//</FONT><FONT face=宋体 size=3>如果是连接点击同一列,则切换该列的升、降序标志,否则记录新的排序列号</P></FONT><FONT size=3>< align=justify>if(ColumnToSort==Column-&gt;Index) Column-&gt;Tag = 1-Column-&gt;Tag; </P>< align=justify>else ColumnToSort = Column-&gt;Index;</P>< align=justify>//</FONT><FONT face=宋体 size=3>调用列表框控件的排序方法</P></FONT><FONT size=3>< align=justify>((TCustomListView *)Sender)-&gt;AlphaSort();</P></FONT><FONT face=宋体 size=3>< align=justify>}</P>< align=justify>我们在上述代码中使用了</FONT><FONT face="宋体, MS Song" size=3>TMainForm</FONT><FONT face=宋体 size=3>类的一个新成员变量</FONT><FONT face="宋体, MS Song" size=3>ColumnToSort</FONT><FONT face=宋体 size=3>,其类型为</FONT><FONT face="宋体, MS Song" size=3>int</FONT><FONT face=宋体 size=3>,用来存放当前准备排序的列号。另外,为了标志当前应该做升序排列还是降序排列,我们还用到了</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>元件的一个常用属性:</FONT><FONT face="宋体, MS Song" size=3>Tag</FONT><FONT face=宋体 size=3>,该属性可以在元件对象中保存一个整数值,该属性的意义可以由程序自行进行解释,例如,窗体上有一组相同元件的多个对象时,就可以为各个对象赋予不同的</FONT><FONT face="宋体, MS Song" size=3>Tag</FONT><FONT face=宋体 size=3>属性值,以此来区分不同的对象。在本程序中,我们就是利用</FONT><FONT face="宋体, MS Song" size=3>TColumnItem</FONT><FONT face=宋体 size=3>对象(即列标框控件的子列标题)的</FONT><FONT face="宋体, MS Song" size=3>Tag</FONT><FONT face=宋体 size=3>属性来标志当前应该做升序排列还是降序排列,其初值为</FONT><FONT face="宋体, MS Song" size=3>0</FONT><FONT face=宋体 size=3>,即缺省操作为降序排列。</P><UL><B><P align=justify><LI>获取文件名对话框 <p></LI></UL></B><P align=justify>大家肯定注意到了,到目前为止,</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>主界面上还有两个按钮的功能未实现,它们分别是“…”和“退出”按钮。其中“…”按钮是为了方便用户查找和获得文件名称而设计的,当用户点击该按钮(</FONT><FONT face="宋体, MS Song" size=3>btnFileName</FONT><FONT face=宋体 size=3>)时,</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>就会弹出如图</FONT><FONT face="宋体, MS Song" size=3>12-1</FONT><FONT face=宋体 size=3>所示的获取文件名对话框,用户可以在其中浏览和查找所需要的文件。</P><P align=justify>图</FONT><FONT face="宋体, MS Song" size=3>12-1</FONT><FONT face=宋体 size=3>是一个典型的</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>打开文件对话框,</FONT><FONT face="宋体, MS Song" size=3>Windows 95</FONT><FONT face=宋体 size=3>以上的操作系统为此功能提供了标准的对话框,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>库把该对话框封装成为了</FONT><FONT face="宋体, MS Song" size=3>OpenDialog</FONT><FONT face=宋体 size=3>控件,在程序中使用起来更为方便。</P><P align=justify>在第八讲中,我们已经在</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>的窗体上添加了一个</FONT><FONT face="宋体, MS Song" size=3>OpenDialog</FONT><FONT face=宋体 size=3>控件,其对象名称为缺省值</FONT><FONT face="宋体, MS Song" size=3>OpenDialog1</FONT><FONT face=宋体 size=3>,现在我们来设置它的属性。</P><P align=justify>首先设置其</FONT><FONT face="宋体, MS Song" size=3>Title</FONT><FONT face=宋体 size=3>属性为“打开一个</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐”,接下来双击</FONT><FONT face="宋体, MS Song" size=3>Filter</FONT><FONT face=宋体 size=3>属性,设置文件类型过滤器。文件类型过滤器是指让对话框在浏览目录时只显示特定的文件类型,例如,如果我们希望对话框中只显示</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐文件,就可以设置其过滤器为“</FONT><FONT face="宋体, MS Song" size=3>*.MP3</FONT><FONT face=宋体 size=3>”,过滤器标题为“</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐”。设置过滤器的对话框如图</FONT><FONT face="宋体, MS Song" size=3>12-2</FONT><FONT face=宋体 size=3>所示,该对话框允许添加多个过滤器,我们在其中输入想要浏览的文件类型及相应的扩展名后,按下“</FONT><FONT face="宋体, MS Song" size=3>OK</FONT><FONT face=宋体 size=3>”按钮确定所作的设置。除了上述属性之外,</FONT><FONT face="宋体, MS Song" size=3>OpenDialog1</FONT><FONT face=宋体 size=3>控件的其它属性均采用缺省值。</P></FONT><FONT size=3><P align=justify>OpenDialog1</FONT><FONT face=宋体 size=3>控件在运行时一般是不可见的,只有程序调用它的</FONT><FONT size=3>Excute()</FONT><FONT face=宋体 size=3>方法时才会弹出图</FONT><FONT size=3>12-1</FONT><FONT face=宋体 size=3>的对话框,该对话框是模态对话框,即只有关闭对话框后,输入焦点才会回到父窗体中。如果用户选择一个文件并按下“打开”按钮,</FONT><FONT size=3>Excute()</FONT><FONT face=宋体 size=3>方法返回真,如果按“取消”按钮或直接关闭窗口,则</FONT><FONT size=3>Excute()</FONT><FONT face=宋体 size=3>返回假。当</FONT><FONT size=3>Excute()</FONT><FONT face=宋体 size=3>返回真时,通过</FONT><FONT size=3>OpenDialog1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>属性便可以获得用户选择的文件名。</P><P align=justify>需要进一步说明的是,</FONT><FONT face="宋体, MS Song" size=3>OpenDialog</FONT><FONT face=宋体 size=3>控件不仅支持选择单个文件也支持同时选中多个文件,其</FONT><FONT face="宋体, MS Song" size=3>Options</FONT><FONT face=宋体 size=3>属性中的标志</FONT><FONT face="宋体, MS Song" size=3>ofAllowMultiSelect</FONT><FONT face=宋体 size=3>可以决定允许单选还是多选。在“…”按钮启动的浏览功能中,我们采用缺省的单选方式,在本讲的后面,心铃还会介绍</FONT><FONT face="宋体, MS Song" size=3>OpenDialog</FONT><FONT face=宋体 size=3>控件多选方式的使用方法。</P><P align=justify>下面是</FONT><FONT face="宋体, MS Song" size=3>btnFileName</FONT><FONT face=宋体 size=3>按钮的事件处理函数</FONT><FONT face="宋体, MS Song" size=3>btnFileNameClick</FONT><FONT face=宋体 size=3>:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::btnFileNameClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>if(OpenDialog1-&gt;Execute()) //</FONT><FONT face=宋体 size=3>调出打开文件对话框</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>从</FONT><FONT size=3>OpenDialog1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>属性中获取用户选择的文件名</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>并将获取的文件名赋给</FONT><FONT size=3>edtFileName</FONT><FONT face=宋体 size=3>编辑框</P></FONT><FONT size=3><P align=justify>edtFileName-&gt;Text=OpenDialog1-&gt;FileName;</P><P align=justify>//</FONT><FONT face=宋体 size=3>把文件名的路径部分和扩展名部分去除,生成缺省的歌曲名称,</P></FONT><FONT size=3><P align=justify>edtSongName-&gt;Text=ChangeFileExt(ExtractFileName(OpenDialog1-&gt;FileName),"");</P><P align=justify>edtSingerName-&gt;Text="";</P><P align=justify>//</FONT><FONT face=宋体 size=3>在</FONT><FONT size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>控件中打开该文件,可以让用户试听音乐的效果</P></FONT><FONT size=3><P align=justify>MediaPlayer1-&gt;FileName=OpenDialog1-&gt;FileName;</P><P align=justify>MediaPlayer1-&gt;Open();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P><P align=justify>实现了文件浏览功能后,程序会出现一个新的问题,就是</FONT><FONT face="宋体, MS Song" size=3>OpenDialog1</FONT><FONT face=宋体 size=3>对话框在浏览文件时会改变程序的工作目录,随后保存记录文件及读取记录文件时就会到错误的目录下打开文件。</P><P align=justify>解决这个问题的方法很简单:只要在</FONT><FONT face="宋体, MS Song" size=3>TMainForm</FONT><FONT face=宋体 size=3>类中添加一个新的成员变量</FONT><FONT face="宋体, MS Song" size=3>AnsiString m_PathName</FONT><FONT face=宋体 size=3>,并为</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>窗体添加</FONT><FONT face="宋体, MS Song" size=3>OnCreate</FONT><FONT face=宋体 size=3>事件处理函数,在其中添加初始化代码</FONT><FONT face="宋体, MS Song" size=3>m_PathName=GetCurrentDir()</FONT><FONT face=宋体 size=3>;然后用成员变量</FONT><FONT face="宋体, MS Song" size=3>m_PathName</FONT><FONT face=宋体 size=3>代替保存记录文件以及读取记录文件代码中对</FONT><FONT face="宋体, MS Song" size=3>GetCurrentDir()</FONT><FONT face=宋体 size=3>的调用。</P><P align=justify>这个问题告诉我们,在程序开发过程中,有时添加一个新功能可能会与已经实现的功能产生冲突,这一方面要求我们认真规划好程序开发的每一步,在程序设计时尽量考虑周到,避免前后矛盾的地方,另一方面说明了测试工作相当重要,只要可能,应在完成一项功能后就测试一项,尽可能早地发现错误并进行改正。</P><UL><B><P align=justify><LI>添加右键关联菜单 <p></LI></UL></B><P align=justify>在使用</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>以及</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>集成开发环境的过程中,我们已经深刻感受到了关联菜单的重要性和灵活性,下面心铃就来介绍一下如何为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>程序添加关联菜单。</P><P align=justify>首先在</FONT><FONT face="宋体, MS Song" size=3>Standard</FONT><FONT face=宋体 size=3>元件栏中找到弹出式菜单控件(</FONT><FONT face="宋体, MS Song" size=3>PopupMenu</FONT><FONT face=宋体 size=3>),为窗体添加一个</FONT><FONT face="宋体, MS Song" size=3>PopupMenu</FONT><FONT face=宋体 size=3>控件,其名称为</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>,然后双击</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>,调出如图</FONT><FONT face="宋体, MS Song" size=3>12-3</FONT><FONT face=宋体 size=3>所示的菜单编辑器。</P><P align=justify>初次打开菜单编辑器时,它会在编辑对象(即</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>菜单)中自动生成一个新的菜单项,对象浏览器也会自动显示出该菜单项的属性。我们在对象浏览器中设置新菜单项的</FONT><FONT face="宋体, MS Song" size=3>Name</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>mnuAdd</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性为“添加多个记录”,表示用户选择该菜单命令时,可以调用前面讲过的</FONT><FONT face="宋体, MS Song" size=3>OpenDialog</FONT><FONT face=宋体 size=3>对话框,一次性获取并添加多条</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>文件记录。</P><P align=justify>设置好一个菜单项并确定后,菜单编辑器会自动生成一个新的菜单项。我们按照同样的方法生成三个新的菜单项,其属性分别为:第二菜单项的</FONT><FONT face="宋体, MS Song" size=3>Name</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>mnuDelete</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性为“删除”(即删除一条记录);第三菜单项为一个分隔条,设置分隔条的方法很简单,只要将其“</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>”属性设为“-”即可;第四菜单项的</FONT><FONT face="宋体, MS Song" size=3>Name</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>mnuSort</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性为“排列”。</P><P align=justify>第四菜单为级联式菜单,即它的下一层还有子菜单。创建子菜单的方法是在菜单编辑器中选中该菜单项,弹出右键关联菜单,并选择其中的“</FONT><FONT face="宋体, MS Song" size=3>Create SubMenu</FONT><FONT face=宋体 size=3>”命令即可。我们在“排列”的下一层子菜单要添加三个菜单项,它们的</FONT><FONT face="宋体, MS Song" size=3>Name</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性分别为:</FONT><FONT face="宋体, MS Song" size=3>mnuSortByFileName</FONT><FONT face=宋体 size=3>(“按文件名”)、</FONT><FONT face="宋体, MS Song" size=3>mnuSortBySongName</FONT><FONT face=宋体 size=3>(“按歌曲名称”)、</FONT><FONT face="宋体, MS Song" size=3>mnuSortBySingerName</FONT><FONT face=宋体 size=3>(“按歌手名称”)。</P><P align=justify>设计好关联菜单控件</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>,接下来我们要把它与某个控件关联起来。大部分可视的</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>元件都具有</FONT><FONT face="宋体, MS Song" size=3>PopupMenu</FONT><FONT face=宋体 size=3>属性,利用该属性可以为元件指定一个关联菜单对象,运行时,用户在该元件区域内点击右键,就会弹出相应的关联菜单。按照这一方法,我们将</FONT><FONT face="宋体, MS Song" size=3>ListView1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>PopupMenu</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>,即让设计好的弹出式菜单与列表框控件</FONT><FONT face="宋体, MS Song" size=3>ListView1</FONT><FONT face=宋体 size=3>相关联。</P><P align=justify>最后要完成菜单命令的事件处理函数,大家应该已经注意到了,</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>中的菜单命令所完成的大部分功能都已经在前面介绍过了,因此心铃在这里只介绍其中“添加多条记录”菜单命令的实现方法,其余的几个命令处理函数就作为练习由读者朋友自己来完成吧。</P><P align=justify>我们在菜单编辑器中双击</FONT><FONT face="宋体, MS Song" size=3>mnuAdd</FONT><FONT face=宋体 size=3>菜单项,由</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>自动生成该菜单的命令处理函数</FONT><FONT face="宋体, MS Song" size=3>mnuAddClick()</FONT><FONT face=宋体 size=3>的框架。该处理函数完成的功能是这样的,首先调出文件浏览对话框,允许用户一次选择多个文件,然后再将这些文件逐条添加到</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>记录集中。下面是</FONT><FONT face="宋体, MS Song" size=3>mnuAddClick</FONT><FONT face=宋体 size=3>函数的代码。</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::mnuAddClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>int i;</P><P align=justify>TListItem * newItem;</P><P align=justify>//</FONT><FONT face=宋体 size=3>设置打开文件对话框的属性,使其能够一次选中多个文件</P></FONT><FONT size=3><P align=justify>OpenDialog1-&gt;Options.Clear();</P><P align=justify>OpenDialog1-&gt;Options&lt;&lt;ofAllowMultiSelect&lt;&lt; ofFileMustExist&lt;&lt; ofHideReadOnly;</P><P align=justify>OpenDialog1-&gt;Title="</FONT><FONT face=宋体 size=3>选择多个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>音乐</FONT><FONT size=3>";</P><P align=justify>if(OpenDialog1-&gt;Execute())//</FONT><FONT face=宋体 size=3>运行打开文件对话框,获取多个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件名</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>AnsiString InputString = InputBox("</FONT><FONT face=宋体 size=3>歌手名称</FONT><FONT size=3>", "</FONT><FONT face=宋体 size=3>请输入歌手名称</FONT><FONT size=3>", "");</P><P align=justify>for(i=0;i&lt;OpenDialog1-&gt;Files-&gt;Count ;i++)</P><P align=justify>{</P><DIR><P align=justify>newItem=ListView1-&gt;Items-&gt;Add();</P><P align=justify>newItem-&gt;Caption = OpenDialog1-&gt;Files-&gt;Strings;</P><P align=justify>newItem-&gt;SubItems-&gt;Add(ChangeFileExt(ExtractFileName(</P><DIR><DIR><DIR><P align=justify>OpenDialog1-&gt;Files-&gt;Strings.c_str()),""));</P></DIR></DIR></DIR><P align=justify>newItem-&gt;SubItems-&gt;Add(InputString);</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>SaveFile();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>恢复</FONT><FONT size=3>OpenDialog1</FONT><FONT face=宋体 size=3>原来的属性设置</P></FONT><FONT size=3><P align=justify>OpenDialog1-&gt;Title="</FONT><FONT face=宋体 size=3>打开一个</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>音乐</FONT><FONT size=3>";</P><P align=justify>OpenDialog1-&gt;Options.Clear();</P><P align=justify>OpenDialog1-&gt;Options&lt;&lt; ofFileMustExist&lt;&lt; ofHideReadOnly; //</FONT><FONT face=宋体 size=3>此处“</FONT><FONT size=3>&lt;&lt;</FONT><FONT face=宋体 size=3>”不是移位操作符</P><P align=justify>}</P><UL><B><P align=justify><LI>退出功能 <p></LI></UL></B><P align=justify>退出功能实现起来非常简单。关闭一个应用程序有很多种方法,它们的原理主要是关闭主窗口或结束消息循环。对</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>来说,只要关闭主窗体</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>,就可以退出整个程序的运行。因此在“退出”按钮的事件处理函数中我们只要简单地调用</FONT><FONT face="宋体, MS Song" size=3>Close()</FONT><FONT face=宋体 size=3>方法就可以了。</P><P align=justify> </P><P align=justify>本讲中我们又为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>添加了一些功能,让它使用起来更加方便,同时我们还学习了</FONT><FONT face="宋体, MS Song" size=3>PopupMenu</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>OpenDialog</FONT><FONT face=宋体 size=3>两种新控件的使用方法,其实,熟练掌握各种元件的使用方法是学习</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>编程的关键点之一,朋友们要想提高</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>编程的水平,除了学习讲座中讲解的内容以外,还要自己多做练习,努力用好</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>的各种元件。</P></FONT><FONT size=3><P align=justify>CBuilder</FONT><FONT face=宋体 size=3>讲座已经过半了,心铃把讲座的电子文档以及第一阶段的源代码上传到了一位朋友的主页上,地址是:</FONT><a href="http://windwind.home.china.com/" target="_blank" ><FONT size=3>http://windwind.home.china.com</FONT></A><FONT face=宋体 size=3>,需要的朋友可以去下载,如果有什么问题,欢迎朋友们来信指教。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>异常处理</P><FONT face=宋体 size=3>< align=justify>在程序设计过程中,我们不仅仅要考虑如何实现程序的功能,还要防止可能出现的异常情况,所谓异常情况就是指在程序运行过程中出现的不正常或不可预料的情况,例如打开的文件不存在、不能分配所需的内存等等。特别是当一个软件要面向大量用户时,它所遇到的运行情况可能千差万别,如果不能够应付各种异常情况,其功能再好再强大也难以弥被这样的缺陷。本讲要介绍的就是如何在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中实现异常处理,并为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>添加异常处理代码。</P><UL><B>< align=justify><LI>传统的异常处理方法
0 b* u! m$ A1 d2 J" M) x- T</LI></UL></B>< align=justify>为了应付可能出现的不正常情况,传统的方法主要是通过条件判断语句来检查是否产生异常的事件。例如,在</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序的</FONT><FONT face="宋体, MS Song" size=3>SaveFile</FONT><FONT face=宋体 size=3>函数中,我们添加了如下的条件语句,以处理可能产生的打开文件错误:</P></FONT><FONT size=3>< align=justify>if(fp==NULL)</P></FONT><FONT face=宋体 size=3>< align=justify>{</P><DIR></FONT><FONT size=3>< align=justify>ShowMessage("</FONT><FONT face=宋体 size=3>不能打开文件</FONT><FONT size=3>Mp3Collect.sav</FONT><FONT face=宋体 size=3>,请检查是否为共享冲突</FONT><FONT size=3>");</P>< align=justify>return;</P></FONT><FONT face=宋体 size=3>< align=justify>}</P></DIR>< align=justify>在检测到了异常事件后,一般需要做两件事,一是显示错误的信息,例如以上代码中对</FONT><FONT face="宋体, MS Song" size=3>ShowMessage()</FONT><FONT face=宋体 size=3>函数的调用,再一个就是中断程序原有的执行流程,因为异常的发生已经使得程序无法满足继续执行原有流程的条件,在</FONT><FONT face="宋体, MS Song" size=3>SaveFile()</FONT><FONT face=宋体 size=3>函数中,如果文件打开失败,就不能继续后面的写文件操作,因此在异常处理中用</FONT><FONT face="宋体, MS Song" size=3>return</FONT><FONT face=宋体 size=3>语句直接返回,中断了保存文件的操作。</P>< align=justify>这种异常处理的方法当然最容易理解,但在大型的软件开发项目中,需要考虑的异常情况非常多,如果每个地方都使用</FONT><FONT face="宋体, MS Song" size=3>if</FONT><FONT face=宋体 size=3>语句来检查错误并处理异常,就会使编程工作变得非常繁杂,源代码的可读性也会大大降低。为了解决这一问题,人们在面向对象编程中找到了更加结构化和更简便的方法来实现异常处理。</P><UL></FONT><B><FONT size=3>< align=justify><LI>CBuilder</FONT><FONT face=宋体 size=3>中的异常处理机制 <p></LI></UL></B></FONT><FONT size=3>< align=justify>CBuilder</FONT><FONT face=宋体 size=3>支持多种异常处理机制,其中包括符合</FONT><FONT size=3>ANSI</FONT><FONT face=宋体 size=3>标准的</FONT><FONT size=3>C++</FONT><FONT face=宋体 size=3>异常处理机制,微软公司提供的</FONT><FONT size=3>Win32</FONT><FONT face=宋体 size=3>结构化异常处理机制,以及基于</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>的异常处理机制,后者是</FONT><FONT size=3>Borland</FONT><FONT face=宋体 size=3>公司建议在</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>编程中采用的异常处理方式。</P>< align=justify>基于</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>的典型异常处理结构的形式如下所示</FONT><FONT size=3><FONT face="宋体, MS Song">:</FONT></P><DIR>< align=justify>try{</P>< align=justify>//</FONT><FONT face=宋体 size=3>可能引起异常的代码段</P>< align=justify>}</P></FONT><FONT size=3>< align=justify>catch</FONT><FONT face=宋体 size=3>(</FONT><FONT size=3>Exception &amp;e</FONT><FONT face=宋体 size=3>){</P></FONT><FONT size=3>< align=justify>//</FONT><FONT face=宋体 size=3>对异常进行处理的代码</P>< align=justify>}</P></DIR>< align=justify>其中</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>为</FONT><FONT face="宋体, MS Song" size=3>C++</FONT><FONT face=宋体 size=3>关键字。</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>用于标志可能产生异常的代码段(</FONT><FONT face="宋体, MS Song" size=3>Block</FONT><FONT face=宋体 size=3>),该代码段用</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>后紧跟的一对大括号{}包括在内。如果这段程序在运行时产生了异常,系统会中止</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>代码段中的代码执行,并查找相应的</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段,如果找到了合适的</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段,即表示错误被捕捉到,这时相应的</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段被执行,如果没有找到合适的</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段,即错误始终没有被捕捉到,则系统会调用</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>库按照缺省的方法来处理异常。当然,如果</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>代码段在运行时一切正常,则</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段是不会被调用的。</P>< align=justify>在上面的异常处理结构中,我们看到,</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句带有一个参数</FONT><FONT face="宋体, MS Song" size=3>Exception &amp;e</FONT><FONT face=宋体 size=3>,该参数是一个异常对象的引用。其中</FONT><FONT face="宋体, MS Song" size=3>Exception</FONT><FONT face=宋体 size=3>是</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>库提供的异常处理类,该类代表了</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>库对异常事件的一个封装。也许有的朋友要问,</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句中的</FONT><FONT face="宋体, MS Song" size=3>Exception &amp;e</FONT><FONT face=宋体 size=3>对象是哪里来的呢?整个程序代码中没有该对象的声明或定义呀?这正是</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>异常处理机制的特点,当异常产生时,</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>库会自动生成该异常对象,并将其作为参数调用合适的</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段。</P></FONT><FONT size=3>< align=justify>Exception</FONT><FONT face=宋体 size=3>类也是其它</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>异常处理类的基类。为了处理不同的异常原因,</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>提供了多种异常处理类,例如,代表申请内存失败的</FONT><FONT size=3>EOutOfMemory</FONT><FONT face=宋体 size=3>异常,代表除数为</FONT><FONT size=3>0</FONT><FONT face=宋体 size=3>的</FONT><FONT size=3>EDivByZero</FONT><FONT face=宋体 size=3>异常,代表文件打开错误的</FONT><FONT size=3>EFOpenError</FONT><FONT face=宋体 size=3>,代表数据库操作错误的</FONT><FONT size=3>EDatabaseError</FONT><FONT face=宋体 size=3>,以及代表多媒体操作错误的</FONT><FONT size=3>EMCIDeviceError</FONT><FONT face=宋体 size=3>等。</P>< align=justify>事实上,一个代码块可能产生不止一种类型的错误,这样,对一个</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>代码段可以采用多个</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段。例如,一个</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>代码段内部可能产生申请内存失败异常</FONT><FONT face="宋体, MS Song" size=3>EOutOfMemory</FONT><FONT face=宋体 size=3>和打开文件错误</FONT><FONT face="宋体, MS Song" size=3>EFOpenError</FONT><FONT face=宋体 size=3>,那么我们可以使用两个</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句来分别监视两种异常情况。采用多个</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句的优点在于,可以对不同类型的异常分别进行捕捉和处理,但有时即使使用了多个</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句后仍无法保证能够捕捉到所有的异常,这时可以使用参数为省略号</FONT><FONT face="宋体, MS Song" size=3>(...)</FONT><FONT face=宋体 size=3>的通用</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句,它可以捕捉尚未捕捉的所有任意类型的异常。</P>< align=justify>下面是使用多个</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>及通用</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>语句的典型例子,</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>代码段中进行了打开文件操作、分配内存操作、文件读操作和整数除法操作,这些操作都有可能引起异常,程序中对打开文件异常和分配内存异常分别进行了处理,对剩下的异常则统一由</FONT><FONT face="宋体, MS Song" size=3>catch(...)</FONT><FONT face=宋体 size=3>语句进行处理。</P></FONT><FONT size=3>< align=justify>try{</P><DIR>< align=justify>FILE * fp=fopen("test.dat","rb");//</FONT><FONT face=宋体 size=3>可能出现</FONT><FONT size=3>EFOpenError</FONT><FONT face=宋体 size=3>类异常</P></FONT><FONT size=3>< align=justify>BYTE * buf=new BYTE[1024];//</FONT><FONT face=宋体 size=3>可能出现</FONT><FONT size=3>EOutOfMemory</FONT><FONT face=宋体 size=3>类异常</P></FONT><FONT size=3>< align=justify>int k,i=100,j=fread(buf,1024,1,fp);// </FONT><FONT face=宋体 size=3>可能出现</FONT><FONT size=3>EReadError</FONT><FONT face=宋体 size=3>类异常</P></FONT><FONT size=3>< align=justify>k=i/j; //</FONT><FONT face=宋体 size=3>可能出现</FONT><FONT size=3>EDivByZero</FONT><FONT face=宋体 size=3>类异常</P></FONT><FONT size=3><P align=justify>fclose(fp);</P><P align=justify>delete buf;</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(EFOpenError &amp;e){</P><DIR><P align=justify>ShowMessage("test.dat</FONT><FONT face=宋体 size=3>:打开文件错误</FONT><FONT size=3>");</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(EOutOfMemory &amp;e){</P><DIR><P align=justify>ShowMessage("</FONT><FONT face=宋体 size=3>内存不足错误</FONT><FONT size=3>");</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(...){</P><DIR><P align=justify>ShowMessage("</FONT><FONT face=宋体 size=3>应用程序出现异常错误</FONT><FONT size=3>");</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>CBuilder</FONT><FONT face=宋体 size=3>为</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>库提供了非常灵活的异常唤醒和异常处理机制,除了由</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>库检测和产生异常之外,还可以由程序通过</FONT><FONT size=3>throw</FONT><FONT face=宋体 size=3>语句来强制产生一个异常,例如下面的代码在检测到异常情况后,强制产生一个异常,并初始化异常消息,交由</FONT><FONT size=3>catch</FONT><FONT face=宋体 size=3>代码段进行处理,后者将显示出现异常的信息。在这段代码中,异常检测仍然采用的是传统的条件语句检测方法,但异常处理则采用的是面向对象的异常处理方式。</P></FONT><FONT size=3><P align=justify>try{</P><DIR><P align=justify>FILE * fp=fopen("test.dat","rb");</P><P align=justify>if(fp==NULL) //</FONT><FONT face=宋体 size=3>检测异常条件</P><DIR></FONT><FONT size=3><P align=justify>throw Exception("test.dat</FONT><FONT face=宋体 size=3>:打开文件错误</FONT><FONT size=3>"); //</FONT><FONT face=宋体 size=3>创建异常对象,并抛出异常对象</P></DIR></FONT><FONT size=3><P align=justify>...//</FONT><FONT face=宋体 size=3>正常的执行代码</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(Exception &amp;e){</P><DIR><P align=justify>ShowMessage(e.Message);//</FONT><FONT face=宋体 size=3>显示异常信息</P></DIR><P align=justify>}</P><UL><B><P align=justify><LI>为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序添加异常处理功能 <p></LI></UL></B><P align=justify>了解了有关</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中异常处理的基础知识后,下面我们就来为</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>添加异常处理代码,以提高程序的容错性和强壮性。</P><P align=justify>实际上,由</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>自动生成的程序框架中已经包含了异常处理代码,在应用程序入口单元文件</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.cpp</FONT><FONT face=宋体 size=3>中,入口函数</FONT><FONT face="宋体, MS Song" size=3>WinMain()</FONT><FONT face=宋体 size=3>便包含有</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段。不过,仅仅依靠这些缺省的异常处理还不够,我们还需要针对不同的错误情况分别进行处理,才能保证程序运行的可靠性。</P><P align=justify>在</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>中,可能出现的异常情况主要是由媒体播放器控件产生的</FONT><FONT face="宋体, MS Song" size=3>EMCIDeviceError</FONT><FONT face=宋体 size=3>和进行文件操作时产生的各种文件操作异常,具体地说,可能产生异常的函数主要有</FONT><FONT face="宋体, MS Song" size=3>btnShowAllClick()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnFindClick()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SaveFile()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnFileNameClick()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>mnuAddClick()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>ListView1SelectItem()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Timer1Timer()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>PlayTheSong()</FONT><FONT face=宋体 size=3>等。不过,为了简化程序代码,心铃准备统一采用了</FONT><FONT face="宋体, MS Song" size=3>Exception</FONT><FONT face=宋体 size=3>类来捕捉所有的</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>异常对象,并利用对象的类名称属性</FONT><FONT face="宋体, MS Song" size=3>ClassName</FONT><FONT face=宋体 size=3>来显示该异常的类别。</P></FONT><FONT size=3><P align=justify>BtnFileNameClick()</FONT><FONT face=宋体 size=3>的主要功能是运行打开文件对话框</FONT><FONT size=3>OpenDialog1</FONT><FONT face=宋体 size=3>,并将获取的文件名赋给文件名称编辑框和媒体播放器,其中,从</FONT><FONT size=3>OpenDialog1-&gt;Execute()</FONT><FONT face=宋体 size=3>开始就可能产生异常,下面是添加了异常处理后的</FONT><FONT size=3>btnFileNameClick()</FONT><FONT face=宋体 size=3>:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::btnFileNameClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>try{//</FONT><FONT face=宋体 size=3>标志可能产生异常的代码段</P><DIR></FONT><FONT size=3><P align=justify>if(OpenDialog1-&gt;Execute()) </FONT><FONT face=宋体 size=3>{</P><DIR></FONT><FONT size=3><P align=justify>MediaPlayer1-&gt;FileName=OpenDialog1-&gt;FileName;</P><P align=justify>edtFileName-&gt;Text=OpenDialog1-&gt;FileName;</P><P align=justify>edtSongName-&gt;Text=ChangeFileExt(ExtractFileName(OpenDialog1-&gt;FileName),"");</P><P align=justify>edtSingerName-&gt;Text="";</P><P align=justify>MediaPlayer1-&gt;Open();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(Exception &amp;e){//</FONT><FONT face=宋体 size=3>异常信息由两部分组成:异常对象的类名称、异常对象的错误消息</P><DIR></FONT><FONT size=3><P align=justify>ShowMessage(AnsiString(e.ClassName())+ ": " + e.Message);</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P></FONT><FONT size=3><P align=justify>mnuAddClick()</FONT><FONT face=宋体 size=3>与</FONT><FONT size=3>btnFileNameClick()</FONT><FONT face=宋体 size=3>相似,此处不再重复。</P></FONT><FONT size=3><P align=justify>ListView1SelectItem()</FONT><FONT face=宋体 size=3>在操作</FONT><FONT size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>控件时容易产生异常,因此</FONT><FONT size=3>try</FONT><FONT face=宋体 size=3>代码段中应包括对</FONT><FONT size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>的操作,添加异常处理后的该函数如下:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm:istView1SelectItem(TObject *Sender, TListItem *Item, bool Selected)</P><P align=justify>{</P><P align=justify>if(Item &amp;&amp; Selected) </FONT><FONT face=宋体 size=3>{</P><DIR><P align=justify>……</FONT><FONT face="宋体, MS Song" size=3>//</FONT><FONT face=宋体 size=3>其它操作</P></FONT><FONT size=3><P align=justify>try{//try</FONT><FONT face=宋体 size=3>代码段包括对</FONT><FONT size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>的操作</P><DIR></FONT><FONT size=3><P align=justify>MediaPlayer1-&gt;FileName=edtFileName-&gt;Text;</P><P align=justify>MediaPlayer1-&gt;Open();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(Exception &amp;e){</P><P align=justify>//</FONT><FONT face=宋体 size=3>异常消息由三部分组成:异常的类名称、</FONT><FONT size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>的错误代码及其错误信息</P><DIR><DIR><DIR></FONT><FONT size=3><P align=justify>ShowMessage(AnsiString(e.ClassName())+" Error " + IntToStr(MediaPlayer1-&gt;Error) + ": " + MediaPlayer1-&gt;ErrorMessage);</P></DIR></DIR></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></DIR><P align=justify>}</P><P align=justify>}</P></FONT><FONT size=3><P align=justify>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>函数体内原有的全部代码都应该被包括在</FONT><FONT size=3>try</FONT><FONT face=宋体 size=3>之内,并且在</FONT><FONT size=3>catch</FONT><FONT face=宋体 size=3>代码中,除了显示异常信息外,还需要清除播放标志,并关闭</FONT><FONT size=3>Timer1</FONT><FONT face=宋体 size=3>。添加了异常处理代码的该函数如下:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::MediaPlayer1Click(TObject *Sender,TMPBtnType Button,bool &amp;DoDefault)</P><P align=justify>{</P><P align=justify>try{</P><DIR><P align=justify>switch(Button){</P><DIR></FONT><FONT face=宋体 size=3><P align=justify>……</FONT><FONT face="宋体, MS Song" size=3>//</FONT><FONT face=宋体 size=3>根据</FONT><FONT face="宋体, MS Song" size=3>Button</FONT><FONT face=宋体 size=3>参数判断用户点击了什么按钮,进行相应的处理</P></DIR><P align=justify>}</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>catch(Exception &amp;e)//</FONT><FONT face=宋体 size=3>捷捉可能产生的异常</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>DoDefault=false;//</FONT><FONT face=宋体 size=3>取消缺省操作</P></FONT><FONT size=3><P align=justify>m_bIsPlaying=false;//</FONT><FONT face=宋体 size=3>清除播放标志</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled=false;//</FONT><FONT face=宋体 size=3>关闭时钟</P></FONT><FONT size=3><P align=justify>EnableButtons(true);//</FONT><FONT face=宋体 size=3>使能命令按钮</P><DIR><DIR><DIR></FONT><FONT size=3><P align=justify>ShowMessage(AnsiString(e.ClassName())+" Error " + IntToStr(MediaPlayer1-&gt;Error) + ": " + e.Message);</P></DIR></DIR></DIR></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P></FONT><FONT size=3><P align=justify>Timer1Timer()</FONT><FONT face=宋体 size=3>与</FONT><FONT size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>的异常处理方式基本一致,也是将函数体内原有的全部代码标志为</FONT><FONT size=3>try</FONT><FONT face=宋体 size=3>代码段,并在</FONT><FONT size=3>catch</FONT><FONT face=宋体 size=3>代码段中进行清除播放标志、关闭</FONT><FONT size=3>Timer1</FONT><FONT face=宋体 size=3>等操作。另外,在时钟处理函数中应该尽量缩短函数的执行时间,避免函数重入引起的问题,因此</FONT><FONT size=3>Timer1Timer()</FONT><FONT face=宋体 size=3>函数的</FONT><FONT size=3>catch</FONT><FONT face=宋体 size=3>代码段最好不要显示异常信息,如果确实需要显示,必须在关闭</FONT><FONT size=3>Timer1</FONT><FONT face=宋体 size=3>之后再显示。</P><P align=justify>由于</FONT><FONT face="宋体, MS Song" size=3>PlayTheSong()</FONT><FONT face=宋体 size=3>被</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1Click()</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>Timer1Timer()</FONT><FONT face=宋体 size=3>调用,而后两个函数中的异常处理代码完全可以处理</FONT><FONT face="宋体, MS Song" size=3>PlayTheSong()</FONT><FONT face=宋体 size=3>可能产生的异常,因此就不需要再单独添加异常处理代码了。</P><P align=justify>最后,</FONT><FONT face="宋体, MS Song" size=3>btnShowAllClick()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnFindClick()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SaveFile()</FONT><FONT face=宋体 size=3>三个函数已经有了基于传统的条件判断式的异常检测和异常处理代码,能够处理打开文件不正常的情况,读者朋友可以自行练习一下,把这一部分的异常处理改用</FONT><FONT face="宋体, MS Song" size=3>try</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>catch</FONT><FONT face=宋体 size=3>代码段来实现。</P><P align=justify> </P><P align=justify>本讲介绍了在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中进行异常处理的内容,不少初学</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>(或其它编程语言)的朋友因为觉得异常处理很复杂或是用处不大,就忽略了这部分内容,其实,异常处理的原理并不复杂,无非是中断产生异常的程序代码,捕捉可能产生的异常并进行相应处理,掌握了这一基本原理之后,就容易理解为什么要引入异常处理机制,以及如何使用异常处理机制了。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>数据库编程基础</P><FONT face=宋体 size=3>< align=justify>到上一讲为止,我们的音乐收藏小程序</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>的第一个版本已经完成了,这个版本的实现是基于文件的,具有简单的记录编辑和管理能力,但它也存在一些缺陷,因此在接下来的几讲中,我们就来编写</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>的第二个版本,第二版将利用数据库来保存记录,并具备访问查询数据库的能力。由于数据库在讲座中是全新的内容,所以在动手编程之前,心铃首先介绍一下在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中进行数据库编程的一些基础知识。</P><UL><B>< align=justify><LI>什么是数据库 ( D. c3 D& R' p' f2 i) V( L6 ~
</LI></UL></B>< align=justify>通常我们在谈论数据库的时候,很容易把数据库(</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>)、数据库管理系统(</FONT><FONT face="宋体, MS Song" size=3>Database Management System</FONT><FONT face=宋体 size=3>)、和数据库应用程序(</FONT><FONT face="宋体, MS Song" size=3>Database Application</FONT><FONT face=宋体 size=3>)混在一起,实际上,它们是构成数据库应用系统的三个组成部分,其中数据库是按照一定的结构组织在一起的相关数据的集合;数据库管理系统是建立、使用和管理数据库的软件系统,简称为</FONT><FONT face="宋体, MS Song" size=3>DBMS</FONT><FONT face=宋体 size=3>;而数据库应用程序则是具有数据库访问能力的应用程序,它提供用户一个访问和操作特定数据库的用户界面。</P>< align=justify>举例来说,我们常用的</FONT><FONT face="宋体, MS Song" size=3>Office</FONT><FONT face=宋体 size=3>办公套件中有一个</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>软件,它就是一种数据库管理系统,如果利用</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>创建一个</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>文件用于保存</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐信息,那么这个</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>文件就是一个数据库,而将要编写的第二版</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.exe</FONT><FONT face=宋体 size=3>能够访问</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>中保存的记录信息,因此它是一个数据库应用程序。</P>< align=justify>数据库和数据库管理系统是密切相关的,通常我们称某某数据库是某一类型的数据库,就是按照该数据库管理系统的名称来命名的。例如,</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>可以称为一个</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>数据库。数据库管理系统不仅可以直接访问某一类型的数据库,还可以提供给其它应用程序一个访问该类型数据库的引擎(即驱动程序),这样,应用程序在访问数据库时就不用考虑数据库的物理存储方式、检索算法的实现等具体问题,而只要把命令传给数据库引擎,然后从数据库引擎处获取结果数据就可以了。</P>< align=justify>根据数据库对数据组织方式的不同,数据库管理系统又分为几种类型,如关系数据库、对象数据库等。其中关系数据库以表格的形式存储数据,是目前应用最广泛的数据库管理系统。我们讲座中要用到的</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>就是一种关系数据库管理系统。一个关系数据库是由一个或多个数据表(</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>)组成,而一个数据表又是由许多结构相同的记录(</FONT><FONT face="宋体, MS Song" size=3>Record</FONT><FONT face=宋体 size=3>)组成,每条记录相当于数据表的一行,数据表的列又称为字段(</FONT><FONT face="宋体, MS Song" size=3>Field</FONT><FONT face=宋体 size=3>),字段定义了该项数据内容的数据类型、数据宽度等。有些数据库是以文件形式存在的,例如</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>的一个</FONT><FONT face="宋体, MS Song" size=3>MDB</FONT><FONT face=宋体 size=3>文件就是一个数据库,其所有的数据表都包含在文件的内部,而有些数据库则是指一个目录,例如</FONT><FONT face="宋体, MS Song" size=3>aradox</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>dBase</FONT><FONT face=宋体 size=3>就是使用目录的数据库,每个数据表在该目录下以独立的文件形式存在。</P><UL></FONT><B><FONT size=3>< align=justify><LI>CBuilder</FONT><FONT face=宋体 size=3>数据库开发环境 <p></LI></UL></B></FONT><FONT size=3>< align=justify>CBuilder</FONT><FONT face=宋体 size=3>在其开发环境中提供了强大的数据库支持,使</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>开发的应用程序能够很方便地具有数据库访问能力。</P>< align=justify>首先,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>提供了</FONT><FONT face="宋体, MS Song" size=3>Borland</FONT><FONT face=宋体 size=3>公司的数据库引擎(</FONT><FONT face="宋体, MS Song" size=3>Borland Database Engine</FONT><FONT face=宋体 size=3>,简称</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>),它是</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>数据库应用程序开发环境的核心。</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>位于应用程序和</FONT><FONT face="宋体, MS Song" size=3>DBMS</FONT><FONT face=宋体 size=3>的数据库引擎之间,使得应用程序可以更加方便地访问不同类型的数据库。</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>支持直接访问</FONT><FONT face="宋体, MS Song" size=3>aradox</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>dBase</FONT><FONT face=宋体 size=3>数据库,通过合适的驱动程序和数据库引擎,</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>还可以访问</FONT><FONT face="宋体, MS Song" size=3>FoxPro</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Infomix</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>DB2</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Oracle</FONT><FONT face=宋体 size=3>等多种流行的桌面数据库和远程数据库,同时</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>也是</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>提供的众多数据库元件的功能基础。</P></FONT><FONT size=3>< align=justify>CBuilder</FONT><FONT face=宋体 size=3>中包含了大量和数据库应用程序相关的元件,它们可分为数据库访问元件和数据控制元件。数据访问元件位于</FONT><FONT size=3>Data Access</FONT><FONT face=宋体 size=3>元件栏中,主要包括</FONT><FONT size=3>DataSource</FONT><FONT face=宋体 size=3>控件、</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>控件、</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件等。数据访问元件在运行过程中是不可见的,它主要是为应用程序提供一条访问数据库的通道。数据控制元件位于</FONT><FONT size=3>Data Controls</FONT><FONT face=宋体 size=3>元件栏中,它们为应用程序提供可视化的用户界面,常用的数据控制元件包括</FONT><FONT size=3>DBNavigator</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>DBGrid</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>DBEdit</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>DBText</FONT><FONT face=宋体 size=3>等。很多数据控制元件都是在普通的用户界面元件的基础上增加了数据感知能力,如</FONT><FONT size=3>DBEdit</FONT><FONT face=宋体 size=3>控件(数据库编辑控件),它不仅具有普通</FONT><FONT size=3>Edit</FONT><FONT face=宋体 size=3>控件的用户输入、编辑、浏览文本的能力,还可以和数据库访问元件关联在一起,从而具有浏览、编辑数据库记录的能力。</P>< align=justify>在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中开发数据库应用程序的基本思路是:<B>使用数据访问元件与数据库建立联接,获取所需的数据集(</FONT><FONT face="宋体, MS Song" size=3>Dataset</FONT><FONT face=宋体 size=3>),并将数据控制元件与数据访问元件相关联,实现用户浏览、操作数据的界面。</P></B></FONT><FONT size=3>< align=justify>CBuilder</FONT><FONT face=宋体 size=3>的数据库开发环境中还包括几个工具软件,它们是</FONT><FONT size=3>BDE</FONT><FONT face=宋体 size=3>管理器(</FONT><FONT size=3>BDE Administrator</FONT><FONT face=宋体 size=3>)、</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>浏览器(</FONT><FONT size=3>SQL Explorer</FONT><FONT face=宋体 size=3>)、数据库桌面(</FONT><FONT size=3>Database Desktop</FONT><FONT face=宋体 size=3>)等。</P></FONT><FONT size=3>< align=justify>BDE</FONT><FONT face=宋体 size=3>管理器是</FONT><FONT size=3>BDE</FONT><FONT face=宋体 size=3>管理和配置的工具软件,它可以创建和维护</FONT><FONT size=3>BDE</FONT><FONT face=宋体 size=3>数据库别名(</FONT><FONT size=3>Alias</FONT><FONT face=宋体 size=3>),安装和删除数据库驱动程序。其中数据库别名是</FONT><FONT size=3>BDE</FONT><FONT face=宋体 size=3>引入的一个重要概念,它的意义和创建方法将在后面进行介绍。</P>< align=justify>数据库桌面是一个简单的数据库管理工具,可以进行许多基于数据表的操作,如创建数据表、修改数据表的结构以及查看和编辑数据表的内容等等。</P></FONT><FONT size=3>< align=justify>SQL</FONT><FONT face=宋体 size=3>浏览器是一个数据库浏览工具,可以浏览数据库中的各种对象,如数据表、字段、索引等,还可以创建和维护数据库别名,编辑和显示数据表中的记录,以及对数据表执行</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>查询等。其中,</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>的全称是结构化查询语言(</FONT><FONT size=3>Structured Query Language</FONT><FONT face=宋体 size=3>),它是目前使用得最广泛的一种标准的数据库查询语言,几乎所有的数据库都支持</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>语言。</P><UL><B>< align=justify><LI>建立一个</FONT><FONT face="宋体, MS Song" size=3>ACCESS</FONT><FONT face=宋体 size=3>数据库 <p></LI></UL></B>< align=justify>下面,我们以</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>程序为例,一步一步地学习如何在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中开发数据库应用程序。第一步需要建立一个数据库。我们以</FONT><FONT face="宋体, MS Song" size=3>Microsoft</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Access 2000</FONT><FONT face=宋体 size=3>为例来说明创建数据库的方法。选用</FONT><FONT face="宋体, MS Song" size=3>Access 2000</FONT><FONT face=宋体 size=3>是因为它是目前比较流行的桌面数据库,使用和管理起来都很方便。</P>< align=justify>首先启动</FONT><FONT face="宋体, MS Song" size=3>Access 2000</FONT><FONT face=宋体 size=3>,选择新建空的数据库,在要求输入数据库名称和路径时输入“</FONT><FONT face="宋体, MS Song" size=3>MP3Collect\MP3Collect.mdb</FONT><FONT face=宋体 size=3>”(即</FONT><FONT face="宋体, MS Song" size=3>Mp3Collect</FONT><FONT face=宋体 size=3>所在目录)。接下来在新建的空白数据库中选择表对象,并双击其中的“使用表设计器创建表”命令,创建一个数据表。</P>< align=justify>在表设计器中,依次定义四个字段:</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>。后面三个字段的意义我们已经非常熟悉了,它们的数据类型定义为文本,</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>的字段大小为</FONT><FONT face="宋体, MS Song" size=3>255</FONT><FONT face=宋体 size=3>,其它两个字段的大小为</FONT><FONT face="宋体, MS Song" size=3>50</FONT><FONT face=宋体 size=3>,并且</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>字段中不允许空字符串,而</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>允许空字符串。另外,我们还要为这三个字段添加允许重复的索引,因为在程序中需要按照这三个字段对数据库进行查询,添加了索引的字段,可以加快查询的速度。</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>是自动编号类型的字段,这个字段的引入是为了给每个记录一个唯一的数字标识,在关系数据库中,这样的数字标识对提高访问效率和系统性能很有用。另外,由于每条记录的</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>是唯一的,我们可以为</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>添加无重复的索引,并且指定其新值的产生方式为递增。设置好这四个字段以后,关闭表设计器,这时</FONT><FONT face="宋体, MS Song" size=3>Access</FONT><FONT face=宋体 size=3>会提示输入新表的名称,这里我们将其命名为</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>。</P>< align=justify>这样,数据库</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>就创建好了,虽然这只是一个简单的单数据表的数据库,但是通过创建这个数据库,我们可以更直观地了解数据库、表、记录、字段、索引的概念,以及它们相互间的关系。有兴趣的朋友不妨再在库中添加一个歌手档案数据库,学习关系数据库中多数据表之间是怎样关联起来的。</P><UL><B>< align=justify><LI>创建</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源和使用数据库别名 <p></LI></UL></B>< align=justify>接下来我们要为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>数据库创建一个</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源。什么是</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>?它的全称是开放式数据库互联(</FONT><FONT face="宋体, MS Song" size=3>Open Database Connectivity</FONT><FONT face=宋体 size=3>),这是一个数据库的访问标准。由于不同的数据库在存储结构、检索算法上存在着很大的差异,为了使应用程序能够通过统一、通用的方法访问不同的数据库,微软提出了</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据库访问标准。目前几乎所有的数据库管理系统都支持</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>标准。</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>也具有</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>接口,可以在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>下访问支持</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>的数据库。</P>< align=justify>数据源是</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>标准中的一个概念,它把一个具体的数据库定义成为一个数据源,数据源中指定了数据库的类型、所使用的驱动程序、所处的路径等信息。应用程序在访问数据库时,只需要和数据源建立联接,而不用考虑数据库所处的具体位置。这样,即使数据库所在的位置(如移到另一个目录中)发生了变化,我们只需要重新设置数据源,而不需要改变应用程序中的代码。</P></FONT><FONT size=3>< align=justify>ODBC</FONT><FONT face=宋体 size=3>数据源由操作系统进行创建和管理。我们打开</FONT><FONT size=3>Windows</FONT><FONT face=宋体 size=3>的控制面板中,找到并运行其中的</FONT><FONT size=3>ODBC</FONT><FONT face=宋体 size=3>数据源工具,就会出现如图</FONT><FONT size=3>14-1</FONT><FONT face=宋体 size=3>所示的</FONT><FONT size=3>ODBC</FONT><FONT face=宋体 size=3>数据源管理器,其中有用户数据源、文件数据源、系统数据源等多个选项。我们在用户数据源选项页中单击“添加”按钮,弹出创建新数据源对话框,在其中选择数据源的驱动程序为</FONT><FONT size=3>Microsoft Access Driver(*.mdb)</FONT><FONT face=宋体 size=3>,然后按下完成按钮。</P>< align=justify>接下来,系统会调用</FONT><FONT face="宋体, MS Song" size=3>Access2000</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源安装对话框,如图</FONT><FONT face="宋体, MS Song" size=3>14-2</FONT><FONT face=宋体 size=3>所示。在其中输入数据源的名称</FONT><FONT face="宋体, MS Song" size=3>MP3CollectDSN</FONT><FONT face=宋体 size=3>,并通过“选择”按钮选择数据库“</FONT><FONT face="宋体, MS Song" size=3>MP3Collect\MP3Collect.mdb</FONT><FONT face=宋体 size=3>”,设置完成后,按下“确定”按钮,新的数据源</FONT><FONT face="宋体, MS Song" size=3>MP3CollectDSN</FONT><FONT face=宋体 size=3>就创建好了。</P>< align=justify>下面还要为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>数据库创建和配置据库别名。前面提到过,别名是</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>引入的重要概念。在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>的数据库访问元件中,很多元件都需要指定一个数据库的名称,这个名称通常就是数据库别名。别名的作用和</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源的作用很类似,它也定义了数据库的一些连接属性,如数据库类型、路径、连接参数等等。基于</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>的数据库应用程序可以通过简单地指定数据库的别名,就可以和数据库建立起连接。</P>< align=justify>创建别名可以通过</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>管理器来完成。在</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>的控制面板中找到并打开</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>管理器,如图</FONT><FONT face="宋体, MS Song" size=3>14-3</FONT><FONT face=宋体 size=3>所示。管理器的左边是</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>选项页和</FONT><FONT face="宋体, MS Song" size=3>Configuration</FONT><FONT face=宋体 size=3>选项页,前者用于创建和维护</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>数据库别名,后者用于配置</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>驱动程序。在</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>选项页中,我们看到,数据源</FONT><FONT face="宋体, MS Song" size=3>MP3CollectDSN</FONT><FONT face=宋体 size=3>也位于其中,说明</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源同样可以作为</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>数据库别名来使用。不过为了说明别名的使用方法,心铃决定创建一个新的别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>。</P><P align=justify>在</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>选项页中调出关联菜单,在其中选择“</FONT><FONT face="宋体, MS Song" size=3>New...</FONT><FONT face=宋体 size=3>”菜单命令,在弹出的“</FONT><FONT face="宋体, MS Song" size=3>New Database Alias</FONT><FONT face=宋体 size=3>”中选择数据库驱动程序名称为“</FONT><FONT face="宋体, MS Song" size=3>Microsoft Access Driver(*.mdb)</FONT><FONT face=宋体 size=3>”,然后确定。这时</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>选项页中多了一项别名,我们将其名称改为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>。</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>管理器的右边显示了新别名的定义,在其中的</FONT><FONT face="宋体, MS Song" size=3>ODBC DSN</FONT><FONT face=宋体 size=3>栏中输入</FONT><FONT face="宋体, MS Song" size=3>MP3CollectDSN</FONT><FONT face=宋体 size=3>,其它的项目采用缺省配置,然后选择菜单命令“</FONT><FONT face="宋体, MS Song" size=3>Object-&gt;Apply</FONT><FONT face=宋体 size=3>”保存数据库别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>的设置,为了验证别名设置是否正确,还可以选择菜单命令“</FONT><FONT face="宋体, MS Song" size=3>Object-&gt;Open</FONT><FONT face=宋体 size=3>”来打开</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,如果打开正确,则说明别名设置是正确的,以后就可以在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>应用程序中使用别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>了。最后,用菜单命令“</FONT><FONT face="宋体, MS Song" size=3>Object-&gt;Close</FONT><FONT face=宋体 size=3>”关闭打开的数据库别名。</P><UL></FONT><B><FONT size=3><P align=justify><LI>MP3Collect</FONT><FONT face=宋体 size=3>的窗体设计 <p></LI></UL></B><P align=justify>完成上面的准备工作之后,我们就可以开始设计新的</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>了。首先在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中新建一个工程(也可在原有工程上改,不过最好要做一个备份),工程名称仍然采用</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>。工程中的主窗体名称为</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>,主窗体类名称为</FONT><FONT face="宋体, MS Song" size=3>TMainForm</FONT><FONT face=宋体 size=3>。</P><P align=justify>新的窗体和第一版的窗体具有同样的界面风格。其中,窗体的上半部分与第一版完全一样,有三个编辑框</FONT><FONT face="宋体, MS Song" size=3>edtFileName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>edtSongName</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>edtSingerName</FONT><FONT face=宋体 size=3>,用于输入记录信息和查询条件,有七个命令按钮</FONT><FONT face="宋体, MS Song" size=3>btnFilename</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnAdd</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnModify</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnDelete</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnFind</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>btnShowAll</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>btnExit</FONT><FONT face=宋体 size=3>,一个循环播放选项框</FONT><FONT face="宋体, MS Song" size=3>chkLoop</FONT><FONT face=宋体 size=3>,以及一个媒体播放器控件</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>。其余的非可视元件如</FONT><FONT face="宋体, MS Song" size=3>Timer1</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>OpenDialog1</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>等也与第一版中完全一样。</P><P align=justify>窗体中的记录显示控件由原来的</FONT><FONT face="宋体, MS Song" size=3>ListView1</FONT><FONT face=宋体 size=3>改为数据库控制元件</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>。并新添了数据库控件</FONT><FONT face="宋体, MS Song" size=3>Database1</FONT><FONT face=宋体 size=3>(</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>类为</FONT><FONT face="宋体, MS Song" size=3>TDatabase</FONT><FONT face=宋体 size=3>)、数据表控件</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>(</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>类为</FONT><FONT face="宋体, MS Song" size=3>TTable1</FONT><FONT face=宋体 size=3>)、数据查询控件</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>(</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>类为</FONT><FONT face="宋体, MS Song" size=3>TQuery</FONT><FONT face=宋体 size=3>)和数据源控件</FONT><FONT face="宋体, MS Song" size=3>DataSource1</FONT><FONT face=宋体 size=3>(</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>类为</FONT><FONT face="宋体, MS Song" size=3>TDataSource</FONT><FONT face=宋体 size=3>)。</P><P align=justify>放置好各种元件之后,还要设置元件的属性。这里只介绍新添的几个数据库控件的属性,其余的与第一版中的一样。</P><P align=justify>首先设置数据库控件</FONT><FONT face="宋体, MS Song" size=3>Database1</FONT><FONT face=宋体 size=3>,该控件代表了应用程序与某个数据库的连接,使程序获得对整个数据库的访问权。设置其</FONT><FONT face="宋体, MS Song" size=3>Database Name</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,指定其连接的数据库为</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,由于别名中已经定义了连接的各种参数,所以</FONT><FONT face="宋体, MS Song" size=3>Database1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>DriveName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>AliasName</FONT><FONT face=宋体 size=3>等属性均不需要进行设置。另外设置其</FONT><FONT face="宋体, MS Song" size=3>LoginPromote</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>false</FONT><FONT face=宋体 size=3>,表示连接时不要弹出登录对话框,登录对话框是用于在与数据库建立连接时提示用户输入用户名和口令的,在本例中并没有为数据库设置口令,所以不需要它。最后,将</FONT><FONT face="宋体, MS Song" size=3>Database1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Connected</FONT><FONT face=宋体 size=3>属性设为真,表示与数据库建立起连接。</P><P align=justify>接下来设置数据表控件</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>。该控件是最基本的数据库访问控件,它代表了实际的数据表对象,其中封装了对数据表的操作,如创建数据表,定义字段、索引,以及添加、修改、删除记录等。我们的程序中使用该控件主要是用于添加、修改和删除记录等操作。选中</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件后,可以在对象监视器看到它的属性非常多,其中大部分都可以采用缺省值,需要设置的有以下三个:在</FONT><FONT face="宋体, MS Song" size=3>DatabaseName</FONT><FONT face=宋体 size=3>属性中,点击右侧的下拉式列表框,选择别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>;在</FONT><FONT face="宋体, MS Song" size=3>TableName</FONT><FONT face=宋体 size=3>属性栏中选择数据表</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>,并在其</FONT><FONT face="宋体, MS Song" size=3>IndexName</FONT><FONT face=宋体 size=3>属性中选取索引</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>;设置</FONT><FONT face="宋体, MS Song" size=3>Active</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>。至于其它属性,请有兴趣学习数据库开发的朋友参考相关资料。</P><P align=justify> </P><P align=justify>由于篇幅所限,其余几个数据库控件的属性设置,以及功能代码的实现就留到下一讲中。本讲的内容涉及到数据库的许多概念,初次接触的朋友可能会感到比较难懂和枯燥,建议感兴趣的朋友们多结合实例,充分理解这些概念。</P><B><P align=justify> </P><P align=justify>名词解释:</P><P align=justify>数据表:</B>一组相关数据的集合,类似于表格,它的每一行称为一条记录,每一列称为一个字段。在关系数据库中,数据表是真正存储数据的地方。</P><B><P align=justify>记录:</B>在数据库中,记录是一个专有名词,它是数据表的单一入口,每条记录由几个字段组成。</P><B><P align=justify>字段:</B>记录中一个特定的数据项目,数据表中的每一列定义了字段的数据类型和数据宽度等属性。</P><B><P align=justify>索引:</B>数据库中为加快对某一字段的查询而保存的特殊信息。</P><B><P align=justify>记录集:</B>应用程序访问数据库时获得的一组数据集合,它可以是一个表中的全部数据,也可以是表的一个子集,或是几个表的合集。</P></FONT><B><FONT size=3><P align=justify>BDE</FONT><FONT face=宋体 size=3>:</B></FONT><FONT size=3>Borland</FONT><FONT face=宋体 size=3>公司开发的数据库引擎,是</FONT><FONT size=3>Delphi</FONT><FONT face=宋体 size=3>以及</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>应用程序访问数据的核心。</P><B><P align=justify>数据源:</B>数据源是</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>标准中的一个概念,它为某一个具体的数据库指定一个名称,数据源中定义了数据库的类型、所使用的驱动程序、所处的路径等信息。</P><B><P align=justify>别名:</B>别名用于基于</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>的数据库应用程序中,它的作用与</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源很类似。设置和维护数据库别名一般是通过工具软件</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>管理器来完成。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>简单数据库查询操作</P><FONT face=宋体 size=3>< align=justify>上一讲我们学习了数据库编程的基础知识,并对</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>进行了一番改造,使其具有数据库访问能力。在本讲中,我们首先设置三个数据库元件</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>DataSource1</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>的属性,接下来学习如何通过</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件实现简单的数据库查询操作。</P><UL><B>< align=justify><LI>设置控件属性
. a! W& U2 z' w+ A+ s3 K/ d</LI></UL></B></FONT><FONT size=3>< align=justify>Query1</FONT><FONT face=宋体 size=3>控件的用途是查询数据库,获取可以显示在窗体中的数据。</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件和</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>控件一样,它们都是从</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>类</FONT><FONT size=3>TDataSet</FONT><FONT face=宋体 size=3>(数据集元件)中继承来的,都代表数据库中一组记录的集合。不同的是,</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>控件代表库中实际存在的一个数据表对象,而</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件则代表一次查询的结果。</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件支持通过</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>进行查询,因此比</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>控件具有更大的灵活性,它可以同时访问多个数据表,可以灵活访问数据表中的行和列,可以实现十分复杂的条件查询。</P></FONT><FONT size=3>< align=justify>SQL</FONT><FONT face=宋体 size=3>的全称是结构化查询语言,它是一种标准的数据库查询语言,具有自己的关键字(</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>中的关键字是不分大小写的,</FONT><FONT size=3>SELECT</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>Select</FONT><FONT face=宋体 size=3>的作用是相同的)和语法,典型的</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>查询语句如下所示:</P></FONT><FONT size=3>< align=justify>SELECT [</FONT><FONT face=宋体 size=3>字段名</FONT><FONT size=3>] FROM [</FONT><FONT face=宋体 size=3>数据表名</FONT><FONT size=3>] WHERE [</FONT><FONT face=宋体 size=3>条件子句</FONT><FONT size=3>]</P></FONT><FONT face=宋体 size=3>< align=justify>其中</FONT><FONT face="宋体, MS Song" size=3>SELECT</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>FROM</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>WHERE</FONT><FONT face=宋体 size=3>都是</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>的关键字。</FONT><FONT face="宋体, MS Song" size=3>SELECT</FONT><FONT face=宋体 size=3>代表查询操作,“字段名”表示返回的记录集中所包含的字段,字段名可以使用通配符</FONT><FONT face="宋体, MS Song" size=3>*</FONT><FONT face=宋体 size=3>,表示查询的数据表中的所有字段,“数据表名”表示在哪个数据表中进行查询,“条件子句”为查询的条件。</P>< align=justify>了解了</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>的基本语法后,下面我们来设置</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性。在对象监视器中双击</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性(该属性为</FONT><FONT face="宋体, MS Song" size=3>TStrings*</FONT><FONT face=宋体 size=3>类型),打开字符串列表编辑器,在其中输入这样两句“</FONT><FONT face="宋体, MS Song" size=3>Select * From MP3Info</FONT><FONT face=宋体 size=3>”和“</FONT><FONT face="宋体, MS Song" size=3>Order by FileName ASC</FONT><FONT face=宋体 size=3>”。注意第二句要另起一行,这样在后面的编程中可以很方便地改变记录的排序方式。这两句合在一起的意思是获取</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>数据表中的所有记录,并以</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>字段为基准按升序方式排序。除了指定</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性外,还要指定它在哪个数据库中进行查询,将其</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>属性设为别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>。然后指定其</FONT><FONT face="宋体, MS Song" size=3>Active</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,其它属性值都接受缺省值。</P></FONT><FONT size=3>< align=justify>DataSource</FONT><FONT face=宋体 size=3>控件从字面上可翻译为数据源控件,不过它与上一讲介绍的</FONT><FONT size=3>ODBC</FONT><FONT face=宋体 size=3>数据源可不是一回事。</FONT><FONT size=3>DataSource</FONT><FONT face=宋体 size=3>控件是一个中间控件,它位于数据集控件(如</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>控件或</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件)和数据控制控件(如</FONT><FONT size=3>DBGrid</FONT><FONT face=宋体 size=3>控件或</FONT><FONT size=3>DBEdit</FONT><FONT face=宋体 size=3>控件)之间,是联系两类控件的桥梁。</FONT><FONT size=3>DataSource</FONT><FONT face=宋体 size=3>控件最重要的属性是它的数据集属性</FONT><FONT size=3>DataSet</FONT><FONT face=宋体 size=3>,在对象浏览器中点击该属性右侧的下拉式列表框,可以看到其中列出了</FONT><FONT size=3>Table1</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>,我们选中</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>,表示</FONT><FONT size=3>DataSource</FONT><FONT face=宋体 size=3>控件从</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>中获取数据。</P></FONT><FONT size=3>< align=justify>DBGrid</FONT><FONT face=宋体 size=3>控件是一种常用的数据控制元件,它以表格的方式显示记录,表格中的行表示记录,而列表示记录的字段。所有的数据控制元件都必须和某个</FONT><FONT size=3>DataSource</FONT><FONT face=宋体 size=3>控件相关联,才能获取所需要的数据,因此我们在这里将</FONT><FONT size=3>DBGrid1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>DataSource</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT size=3>DataSource1</FONT><FONT face=宋体 size=3>。指定</FONT><FONT size=3>DBGrid1</FONT><FONT face=宋体 size=3>的数据来源后,我们可以看到</FONT><FONT size=3>DBGrid1</FONT><FONT face=宋体 size=3>的表格中立即显示出相应的记录了。</P>< align=justify>缺省情况下,</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>会显示数据集的全部字段,并以字段的名称显示在列标题中,我们可以在设计时通过</FONT><FONT face="宋体, MS Song" size=3>DBGrid</FONT><FONT face=宋体 size=3>控件的列编辑器修改列的数目、标题以及布局等。在对象浏览器中双击</FONT><FONT face="宋体, MS Song" size=3>Columns</FONT><FONT face=宋体 size=3>属性,打开列编辑器,此时列编辑器中的内容还是空的,因此我们在列编辑器中点击鼠标右键,选择关联菜单中的“</FONT><FONT face="宋体, MS Song" size=3>Add All Field</FONT><FONT face=宋体 size=3>”命令,先把数据集中的所有字段添加进来。由于我们不希望将记录的编号显示出来,所以要删除其中的“</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>”字段。</P>< align=justify>接下来我们来设置各列的列标题。首先选中“</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>”列,这时可以在对象浏览器中看到该列的各种属性,其中</FONT><FONT face="宋体, MS Song" size=3>FieldName</FONT><FONT face=宋体 size=3>属性为“</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>”,表示该列显示“</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>”字段的内容,列对象的</FONT><FONT face="宋体, MS Song" size=3>Title</FONT><FONT face=宋体 size=3>属性为复合属性,展开</FONT><FONT face="宋体, MS Song" size=3>Title</FONT><FONT face=宋体 size=3>属性,将其中的</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>子属性改为“文件名称”,然后设置“</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>”列的列宽度,其缺省的</FONT><FONT face="宋体, MS Song" size=3>Width</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>-1</FONT><FONT face=宋体 size=3>,表示根据字段的宽度自动设置列宽度,我们可以根据窗体的布局为其重新设置一个实际的值。按照同样的方法,我们继续把“</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>”、“</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>”的列标题改为“歌曲名称”和“歌手名称”。</P>< align=justify>设置好</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>控件的列对象的属性后,接下来还要设置它的</FONT><FONT face="宋体, MS Song" size=3>Options</FONT><FONT face=宋体 size=3>属性,该属性决定了显示记录的方式。展开</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Options</FONT><FONT face=宋体 size=3>属性,可以看见其中有十多项选项,将其中的</FONT><FONT face="宋体, MS Song" size=3>dgEditing</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>dgAlwaysShowEdit</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>dgMultiSelect</FONT><FONT face=宋体 size=3>三个选项设为</FONT><FONT face="宋体, MS Song" size=3>false</FONT><FONT face=宋体 size=3>,其余的选项都设为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,如此设置可以屏蔽在</FONT><FONT face="宋体, MS Song" size=3>DBGrid</FONT><FONT face=宋体 size=3>中直接修改记录以及同时选中多条记录的功能。另外还可以设置</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>ReadOnly</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,使用户不能在网格中进行添加、修改、删除记录的操作。最后,设置</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>opupMenu</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>opupMenu1</FONT><FONT face=宋体 size=3>,为其指定关键菜单。</P>< align=justify>现在所有元件的属性都设置好了,下面我们来看看访问数据库的具体方法。为了简洁起见,下面的代码中都没有异常处理措施,读者朋友可以根据第</FONT><FONT face="宋体, MS Song" size=3>13</FONT><FONT face=宋体 size=3>讲的内容自己添加相应的异常处理代码。</P><UL><B>< align=justify><LI>实现查询功能 <p></LI></UL></B></FONT><FONT size=3>< align=justify>Table</FONT><FONT face=宋体 size=3>控件和</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件都可以实现查询,但</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>不支持</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>,只能通过数据表中的索引实现比较简单的检索功能(在后面还会用到</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>的查询功能),因此心铃决定用</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件进行查询,提供显示在</FONT><FONT size=3>DBGrid1</FONT><FONT face=宋体 size=3>中的数据。</P>< align=justify>所有的查询都是通过设置</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性来完成的。实现显示所有记录的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句最简单,即前面给出的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性。下面是</FONT><FONT face="宋体, MS Song" size=3>btnShowAllClick</FONT><FONT face=宋体 size=3>事件处理函数的新代码,其中给出了在运行时改变</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性的方法。</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm::btnShowAllClick(TObject *Sender)</P>< align=justify>{</P>< align=justify>Query1-&gt;Close();//</FONT><FONT face=宋体 size=3>先关闭上一次查询</P></FONT><FONT size=3>< align=justify>Query1-&gt;SQL-&gt;Clear();//</FONT><FONT face=宋体 size=3>清除原来的</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>语句</P></FONT><FONT size=3>< align=justify>Query1-&gt;SQL-&gt;Add("Select * from MP3Info");//</FONT><FONT face=宋体 size=3>添加一个字符串,</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>属性由多个字符串组合而成</P></FONT><FONT size=3>< align=justify>Query1-&gt;SQL-&gt;Add("Order By FileName ASC");</P>< align=justify>ColumnToSort=0;//</FONT><FONT face=宋体 size=3>记下当前排序的基准列为“</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>”</P></FONT><FONT size=3>< align=justify>m_IsAsc=1;//</FONT><FONT face=宋体 size=3>记下当前排序的方式为升序方式</P></FONT><FONT size=3>< align=justify>Query1-&gt;Open(); //</FONT><FONT face=宋体 size=3>设置好</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>属性后,打开</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>,获取数据并自动更新</FONT><FONT size=3>DBGrid1</P></FONT><FONT face=宋体 size=3>< align=justify>}</P>< align=justify>在改变</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性之前,首先应将上一次查询关闭。</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性是一个</FONT><FONT face="宋体, MS Song" size=3>TStrings</FONT><FONT face=宋体 size=3>对象指针,它将多个字符串组成一个完整的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>查询语句,其中的</FONT><FONT face="宋体, MS Song" size=3>Order By</FONT><FONT face=宋体 size=3>是</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>中的关键字,表示按照某一个字段进行排序,</FONT><FONT face="宋体, MS Song" size=3>ASC</FONT><FONT face=宋体 size=3>是排序方式关键字,表示升序方式。</FONT><FONT face="宋体, MS Song" size=3>ColumnToSort</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>m_IsAsc</FONT><FONT face=宋体 size=3>是</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>类的成员变量,用于保存排序的基准列号和排序方式,有关排序的内容还要在下一节仔细介绍。设置好</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性后,调用</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Open()</FONT><FONT face=宋体 size=3>方法,该方法会通过</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>引擎向数据库进行一次查询操作,获取所需的数据,并自动更新</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>中显示的数据。</P><P align=justify>条件查询操作需要使用</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句中的</FONT><FONT face="宋体, MS Song" size=3>WHERE</FONT><FONT face=宋体 size=3>条件子句。查询的原理是依次读取三个条件输入框的内容,如果某一条件输入框不为空,则添加一个查询条件。这里使用的查询条件的语法如下所示:</P></FONT><FONT size=3><P align=justify>[</FONT><FONT face=宋体 size=3>字段名</FONT><FONT size=3>] Like '</FONT><FONT face=宋体 size=3>带通配符的字符串</FONT><FONT size=3>'</P></FONT><FONT face=宋体 size=3><P align=justify>其中</FONT><FONT face="宋体, MS Song" size=3>[</FONT><FONT face=宋体 size=3>字段名</FONT><FONT face="宋体, MS Song" size=3>]</FONT><FONT face=宋体 size=3>为要检查的字段,</FONT><FONT face="宋体, MS Song" size=3>LIKE</FONT><FONT face=宋体 size=3>为</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>的关键字,表示将字段内容与“带通配符的字符串”进行比较,看是否符合给定的模式。“带通配符的字符串”需要用单引号包括起来,常用的通配符有“</FONT><FONT face="宋体, MS Song" size=3>%</FONT><FONT face=宋体 size=3>”、“?”等。其中“</FONT><FONT face="宋体, MS Song" size=3>%</FONT><FONT face=宋体 size=3>”表示任意字符串。例如,下面的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句表示从</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>中取出所有</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>字段中包括“</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>”字样的记录:</P></FONT><FONT size=3><P align=justify>SELECT * FROM MP3Info WHERE FileName Like %MP3%</P></FONT><FONT face=宋体 size=3><P align=justify>另外,在</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>中,各个查询条件之间是逻辑与的关系,因此多个查询条件之间要用关键字</FONT><FONT face="宋体, MS Song" size=3>AND</FONT><FONT face=宋体 size=3>进行连接,表示只有符合所有查询条件的记录才是所需要的记录。下面是</FONT><FONT face="宋体, MS Song" size=3>btnFindClick</FONT><FONT face=宋体 size=3>事件处理函数的新代码:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::btnFindClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>Query1-&gt;Close();//</FONT><FONT face=宋体 size=3>首先关闭</FONT><FONT size=3>Query1</P><P align=justify>Query1-&gt;SQL-&gt;Clear();//</FONT><FONT face=宋体 size=3>清除原有的</FONT><FONT size=3>SQL</FONT><FONT face=宋体 size=3>语句</P></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add("Select * from MP3Info");//</FONT><FONT face=宋体 size=3>表示从数据表中</FONT><FONT size=3>MP3Info</FONT><FONT face=宋体 size=3>中查询</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>edtFileName</FONT><FONT face=宋体 size=3>不为空,则添加对</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>字段的查询,注意不要漏了其中的单引号</P></FONT><FONT size=3><P align=justify>if(!edtFileName-&gt;Text.IsEmpty())</P><DIR><P align=justify>Query1-&gt;SQL-&gt;Add(" where FileName Like '%"+edtFileName-&gt;Text+"%'");</P></DIR><P align=justify>//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>edtSongName</FONT><FONT face=宋体 size=3>不为空,则添加对</FONT><FONT size=3>SongName</FONT><FONT face=宋体 size=3>字段的查询,由于整个条件子句中只有</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>一个</FONT><FONT size=3>WHERE</FONT><FONT face=宋体 size=3>关键字,多个条件之间需要用</FONT><FONT size=3>AND</FONT><FONT face=宋体 size=3>关键字连接,所以要进行一些特殊处理</P></FONT><FONT size=3><P align=justify>if(!edtSongName-&gt;Text.IsEmpty())</P><P align=justify>{</P><DIR><P align=justify>if(Query1-&gt;SQL-&gt;Count&gt;1)//</FONT><FONT face=宋体 size=3>判断是否已经包含查询条件了</P><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add(" and ");//</FONT><FONT face=宋体 size=3>如果是,则用</FONT><FONT size=3>AND</FONT><FONT face=宋体 size=3>连接本查询条件</P></DIR></FONT><FONT size=3><P align=justify>else</P><DIR><P align=justify>Query1-&gt;SQL-&gt;Add(" where ");//</FONT><FONT face=宋体 size=3>否则用</FONT><FONT size=3>WHERE</FONT><FONT face=宋体 size=3>引出查询条件</P></DIR></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add("SongName Like '%"+edtSongName-&gt;Text+"%'");//</FONT><FONT face=宋体 size=3>添加一个查询条件</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>edtSingerName</FONT><FONT face=宋体 size=3>编辑框中不为空,则添加对</FONT><FONT size=3>SingerName</FONT><FONT face=宋体 size=3>字段的查询</P></FONT><FONT size=3><P align=justify>if(!edtSingerName-&gt;Text.IsEmpty())</P><P align=justify>{</P><DIR><P align=justify>if(Query1-&gt;SQL-&gt;Count&gt;1)//</FONT><FONT face=宋体 size=3>判断是否已经包含查询条件了</P><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add(" and ");//</FONT><FONT face=宋体 size=3>如果是,则用</FONT><FONT size=3>AND</FONT><FONT face=宋体 size=3>连接本查询条件</P></DIR></FONT><FONT size=3><P align=justify>else</P><DIR><P align=justify>Query1-&gt;SQL-&gt;Add(" where ");//</FONT><FONT face=宋体 size=3>否则用</FONT><FONT size=3>WHERE</FONT><FONT face=宋体 size=3>引出查询条件</P></DIR></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add("SingerName Like '%"+edtSingerName-&gt;Text+"%'");//</FONT><FONT face=宋体 size=3>添加一个查询条件</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add(" Order By FileName ASC");//</FONT><FONT face=宋体 size=3>添加排序子句</P></FONT><FONT size=3><P align=justify>ColumnToSort=0;//</FONT><FONT face=宋体 size=3>记下当前排序的基准列为“</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>”</P></FONT><FONT size=3><P align=justify>m_IsAsc=1;//</FONT><FONT face=宋体 size=3>记下当前排序的方式为升序方式</P></FONT><FONT size=3><P align=justify>Query1-&gt;Open();</P></FONT><FONT face=宋体 size=3><P align=justify>}</P><UL><B><P align=justify><LI>实现排序 <p></LI></UL></B><P align=justify>前面我们已经用到了</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语言的排序子句,排序子句是由关键词</FONT><FONT face="宋体, MS Song" size=3>Order By</FONT><FONT face=宋体 size=3>引出的,其后跟一个或多个字段,表示以某个字段为基准进行排序,如果有多个字段,则先按第一个字段进行排序,如果出现第一个字段的内容相同,再按第二个字段排序,依此类推。另外还可以用</FONT><FONT face="宋体, MS Song" size=3>ASC</FONT><FONT face=宋体 size=3>(升序方式)和</FONT><FONT face="宋体, MS Song" size=3>DESC</FONT><FONT face=宋体 size=3>(降序方式)规定其排序的方式。</P><P align=justify>我们在</FONT><FONT face="宋体, MS Song" size=3>TMainForm</FONT><FONT face=宋体 size=3>中添加了一个成员变量</FONT><FONT face="宋体, MS Song" size=3>m_IsAsc</FONT><FONT face=宋体 size=3>,用于保存当前排序的方式,注意应在窗体的初始化函数</FONT><FONT face="宋体, MS Song" size=3>FormCreate</FONT><FONT face=宋体 size=3>中将</FONT><FONT face="宋体, MS Song" size=3>m_IsAsc</FONT><FONT face=宋体 size=3>初始化为</FONT><FONT face="宋体, MS Song" size=3>1</FONT><FONT face=宋体 size=3>。下面是菜单命令</FONT><FONT face="宋体, MS Song" size=3>mnuSortByFileName</FONT><FONT face=宋体 size=3>的命令处理函数:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::mnuSortByFileNameClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>if(ColumnToSort!=0)//</FONT><FONT face=宋体 size=3>如果以前不是按</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>字段排序,则改为按</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>字段排序</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;Close();</P><P align=justify>Query1-&gt;SQL-&gt;Delete(Query1-&gt;SQL-&gt;Count-1);//</FONT><FONT face=宋体 size=3>清除原来的排序子句</P></FONT><FONT size=3><P align=justify>Query1-&gt;SQL-&gt;Add("Order By FileName ASC");//</FONT><FONT face=宋体 size=3>添加新的排序子句</P></FONT><FONT size=3><P align=justify>ColumnToSort=0;//</FONT><FONT face=宋体 size=3>记下当前排序的基准列为“</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>”</P></FONT><FONT size=3><P align=justify>m_IsAsc=1; //</FONT><FONT face=宋体 size=3>记下当前排序的方式为升序方式</P></FONT><FONT size=3><P align=justify>Query1-&gt;Open();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>else //</FONT><FONT face=宋体 size=3>否则切换排序的方式</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;Close();</P><P align=justify>Query1-&gt;SQL-&gt;Delete(Query1-&gt;SQL-&gt;Count-1);</P><P align=justify>if(m_IsAsc)</P><DIR><P align=justify>Query1-&gt;SQL-&gt;Add("Order By FileName DESC");//</FONT><FONT face=宋体 size=3>如果原来是升序,改为降序</P></DIR></FONT><FONT size=3><P align=justify>else</P><DIR><P align=justify>Query1-&gt;SQL-&gt;Add("Order By FileName Asc");//</FONT><FONT face=宋体 size=3>如果原来是降序,改为升序</P></DIR></FONT><FONT size=3><P align=justify>m_IsAsc=1-m_IsAsc;//</FONT><FONT face=宋体 size=3>改变</FONT><FONT size=3>m_IsAsc</FONT><FONT face=宋体 size=3>的值,反映排序方式的改变</P></FONT><FONT size=3><P align=justify>Query1-&gt;Open();//</FONT><FONT face=宋体 size=3>打开</FONT><FONT size=3>Query1</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P><P align=justify>另外两个排序菜单命令的处理函数</FONT><FONT face="宋体, MS Song" size=3>mnuSortBySongNameClick</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>mnuSortBySingerNameClick</FONT><FONT face=宋体 size=3>的实现方法与</FONT><FONT face="宋体, MS Song" size=3>mnuSortByFileNameClick</FONT><FONT face=宋体 size=3>很类似,就交给读者朋友自己完成吧。</P><P align=justify>最后,还要响应</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>OnTitleClick</FONT><FONT face=宋体 size=3>事件,允许用户通过单击</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>的列标题来改变排序的方式。下面是</FONT><FONT face="宋体, MS Song" size=3>DBGrid1TitleClick</FONT><FONT face=宋体 size=3>函数的新代码:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm:BGrid1TitleClick(TColumn *Column)</P><P align=justify>{</P><DIR><P align=justify>switch(Column-&gt;Index)//</FONT><FONT face=宋体 size=3>用户点击的列号</P></DIR><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>case 0://</FONT><FONT face=宋体 size=3>如果是第一列,则按</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>进行排序</P></FONT><FONT size=3><P align=justify>mnuSortByFileNameClick(NULL);</P><P align=justify>break;</P></DIR><P align=justify>case 1: //</FONT><FONT face=宋体 size=3>如果是第二列,则按</FONT><FONT size=3>SongName</FONT><FONT face=宋体 size=3>进行排序</P><DIR></FONT><FONT size=3><P align=justify>mnuSortBySongNameClick(NULL);</P><P align=justify>break;</P><P align=justify>case 2: //</FONT><FONT face=宋体 size=3>如果是第三列,则按</FONT><FONT size=3>SingerName</FONT><FONT face=宋体 size=3>进行排序</P></FONT><FONT size=3><P align=justify>mnuSortBySingerNameClick(NULL);</P><P align=justify>break;</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P><P align=justify>本讲我们学习了利用</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件和</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句实现简单数据库查询的方法,</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>实际上是数据库编程的核心内容之一,因此心铃建议想进一步学习数据库开发的读者朋友一定要掌握好</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>的语法和用法。在下一讲中,我们将学习简单的数据库编辑操作,即添加、修改和删除记录的方法。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>简单数据库编辑操作</P><FONT face=宋体 size=3>< align=justify>上一讲我们学习了利用</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件和</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句实现简单数据库查询的方法,在本讲中,我们将要学习如何利用</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件来实现添加、修改、删除记录等数据库编辑操作。</P><UL><B>< align=justify><LI>获取当前记录 - J) U# W% o4 C2 S3 s2 H" V1 w
</LI></UL></B>< align=justify>在上一讲中我们曾经比较过</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件和</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件的异同,并指出</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件是通过</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句来操作数据库的,</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句除了可以实现查询外,也可以通过关键字</FONT><FONT face="宋体, MS Song" size=3>INSERT</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>UPDATE</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>DELETE</FONT><FONT face=宋体 size=3>来实现添加、修改和删除记录的操作,但是这一类</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>语句对初学者来说有一定难度,而</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件提供有</FONT><FONT face="宋体, MS Song" size=3>Insert</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Edit</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Delete</FONT><FONT face=宋体 size=3>等方法,实现简单的数据库编辑操作比</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>控件更为容易,因此心铃决定以</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件为例来介绍进行数据库编辑操作的方法。</P></FONT><FONT size=3>< align=justify>MP3Collect</FONT><FONT face=宋体 size=3>使用的</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>Table1</FONT><FONT face=宋体 size=3>是两个独立的控件,用户看到窗体上的数据是由</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>提供的,怎样才能让</FONT><FONT size=3>Table1</FONT><FONT face=宋体 size=3>控件知道用户当前操作的是哪一条记录呢?</P>< align=justify>为了解决这个问题,我们需要先学习一些基础知识。数据集控件(</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>或</FONT><FONT face="宋体, MS Song" size=3>Query</FONT><FONT face=宋体 size=3>)除了提供一组记录集合之外,还保存了一个称为光标(</FONT><FONT face="宋体, MS Song" size=3>Cursor</FONT><FONT face=宋体 size=3>)的指针,用于指向当前记录,程序可以通过调用</FONT><FONT face="宋体, MS Song" size=3>TDataSet</FONT><FONT face=宋体 size=3>类的</FONT><FONT face="宋体, MS Song" size=3>First()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Next()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>rior()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>MoveBy()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Last()</FONT><FONT face=宋体 size=3>等方法控制记录光标的移动。</P>< align=justify>如果数据集控件与某个数据控制控件相关联,则还可以通过数据控制控件来移动记录光标,例如,</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>主窗体上的</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件和</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>控件建立了关联(通过</FONT><FONT face="宋体, MS Song" size=3>DataSource1</FONT><FONT face=宋体 size=3>控件),当用户在</FONT><FONT face="宋体, MS Song" size=3>DBGrid1</FONT><FONT face=宋体 size=3>中选择不同的行时,同时也会把</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>的记录光标移到相应的位置上。</P>< align=justify>无论用哪种方式改变了数据集控件的当前记录光标,都会触发数据集控件的</FONT><FONT face="宋体, MS Song" size=3>AfterScroll</FONT><FONT face=宋体 size=3>事件。因此,我们要为</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件添加</FONT><FONT face="宋体, MS Song" size=3>AfterScroll</FONT><FONT face=宋体 size=3>事件的处理函数</FONT><FONT face="宋体, MS Song" size=3>Query1AfterScroll</FONT><FONT face=宋体 size=3>,在其中获取当前记录的内容并显示在三个编辑框中,同时在</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>中打开相应的音乐文件,另外还要利用</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>FindKey()</FONT><FONT face=宋体 size=3>方法将</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>的记录光标调整到相同的记录上。</P>< align=justify>前一讲中介绍过,</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件也具有一定的查询能力,</FONT><FONT face="宋体, MS Song" size=3>FindKey()</FONT><FONT face=宋体 size=3>就是它的查询方法之一,其原理是利用数据表的索引进行快速的检索操作。查询的步骤如下:首先设置</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>IndexName</FONT><FONT face=宋体 size=3>属性。在窗体设计阶段,我们已经将</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>IndexName</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>,选择</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>作为</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>的索引,是因为每个记录的</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>值是唯一的,不用担心会检索出重复的记录。在运行时确认</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>处于打开的状态,然后调用其</FONT><FONT face="宋体, MS Song" size=3>FindKey()</FONT><FONT face=宋体 size=3>方法,查找数据表中</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>值与</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的当前记录</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>值相等的记录,同时将</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>的光标移到新的记录上。下面就是</FONT><FONT face="宋体, MS Song" size=3>Query1AfterScroll</FONT><FONT face=宋体 size=3>的实现代码。</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm:uery1AfterScroll(TDataSet *DataSet)</P>< align=justify>{</P>< align=justify>if(Query1-&gt;State==dsBrowse )//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件当前处于记录浏览状态</P>< align=justify>{</P><DIR></FONT><FONT size=3>< align=justify>if(!Query1-&gt;IsEmpty())//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>的数据集不为空</P>< align=justify>{</P><DIR></FONT><FONT size=3>< align=justify>//</FONT><FONT face=宋体 size=3>声明</FONT><FONT size=3>TVarRec</FONT><FONT face=宋体 size=3>类型的变量数组,</FONT><FONT size=3>FindKey()</FONT><FONT face=宋体 size=3>方法使用该类型的数组作为参数。</P></DIR></DIR></FONT><FONT size=3>< align=justify>TVarRec KeyValues[1]; </P>< align=justify>//</FONT><FONT face=宋体 size=3>获得</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的当前记录的</FONT><FONT size=3>ID</FONT><FONT face=宋体 size=3>字段内容,并赋给</FONT><FONT size=3>KeyValues</FONT><FONT face=宋体 size=3>数组中的第一个元素</P><DIR><DIR></FONT><FONT size=3>< align=justify>KeyValues[0]=Query1-&gt;FieldByName("ID")-&gt;AsInteger;</P>< align=justify>if(!Table1-&gt;Active) //</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>Table1</FONT><FONT face=宋体 size=3>还未打开,将其打开</P><DIR><DIR></FONT><FONT size=3>< align=justify>Table1-&gt;Active =true;</P></DIR></DIR></DIR></DIR>< align=justify>Table1-&gt;FindKey(KeyValues,0);//</FONT><FONT face=宋体 size=3>调用</FONT><FONT size=3>FindKey()</FONT><FONT face=宋体 size=3>方法,查找并定位新的记录光标</P></FONT><FONT size=3>< align=justify>//</FONT><FONT face=宋体 size=3>获取</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件当前记录的各个字段内容,并赋给相应的编辑框</P><DIR><DIR></FONT><FONT size=3>< align=justify>edtFileName-&gt;Text=Query1-&gt;FieldByName("FileName")-&gt;AsString;</P>< align=justify>edtSongName-&gt;Text=Query1-&gt;FieldByName("SongName")-&gt;AsString;</P>< align=justify>edtSingerName-&gt;Text=Query1-&gt;FieldByName("SingerName")-&gt;AsString;</P></DIR></DIR>< align=justify>//</FONT><FONT face=宋体 size=3>在</FONT><FONT size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>中打开相应的音乐文件</P><DIR><DIR></FONT><FONT size=3>< align=justify>MediaPlayer1-&gt;FileName=Query1-&gt;FieldByName("FileName")-&gt;AsString;</P>< align=justify>MediaPlayer1-&gt;Open();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></DIR><P align=justify>}</P><P align=justify>}</P><UL><B><P align=justify><LI>移动当前记录 <p></LI></UL></B><P align=justify>为了实现向前、向后浏览和连续播放的功能,我们需要通过程序控制数据集的光标移动。其中,向前移动一条记录使用</FONT><FONT face="宋体, MS Song" size=3>TDataSet</FONT><FONT face=宋体 size=3>类的</FONT><FONT face="宋体, MS Song" size=3>Prior()</FONT><FONT face=宋体 size=3>方法,向后移动一条记录使用</FONT><FONT face="宋体, MS Song" size=3>Next()</FONT><FONT face=宋体 size=3>方法,移动到第一条记录使用</FONT><FONT face="宋体, MS Song" size=3>First()</FONT><FONT face=宋体 size=3>方法,移动到最后一条记录使用</FONT><FONT face="宋体, MS Song" size=3>Last()</FONT><FONT face=宋体 size=3>方法。</FONT><FONT face="宋体, MS Song" size=3>TDataSet</FONT><FONT face=宋体 size=3>类还提供了两个布尔类型的属性</FONT><FONT face="宋体, MS Song" size=3>Bof</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>Eof</FONT><FONT face=宋体 size=3>,用于确定当前的记录是否是数据集中的第一个记录或最后一个记录。下面给出用户点击</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Next</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>Prev</FONT><FONT face=宋体 size=3>按钮时的事件处理代码(完整的事件处理函数参见第</FONT><FONT face="宋体, MS Song" size=3>11</FONT><FONT face=宋体 size=3>讲):</P><DIR></FONT><FONT size=3><P align=justify>case Mplayer::btNext: //</FONT><FONT face=宋体 size=3>如果用户点击</FONT><FONT size=3>Next</FONT><FONT face=宋体 size=3>按钮,播放下一首</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(false);//</FONT><FONT face=宋体 size=3>使记录操作按钮失效</P></FONT><FONT size=3><P align=justify>Query1-&gt;Next();//</FONT><FONT face=宋体 size=3>使</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的记录光标向后移动一条记录</P></FONT><FONT size=3><P align=justify>if(Query1-&gt;Eof)//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>Eof</FONT><FONT face=宋体 size=3>属性为真,则表示已到了最后一个记录</P><DIR><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;First();//</FONT><FONT face=宋体 size=3>循环到当前数据集的第一个记录</P></DIR></DIR></FONT><FONT size=3><P align=justify>m_bIsPlaying=true; //</FONT><FONT face=宋体 size=3>设置</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>标志</P></FONT><FONT size=3><P align=justify>DoDefault=false; //</FONT><FONT face=宋体 size=3>不执行缺省的按钮事件</P></FONT><FONT size=3><P align=justify>PlayTheSong();//</FONT><FONT face=宋体 size=3>执行打开</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件、播放</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件等操作</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled=true; //</FONT><FONT face=宋体 size=3>打开定时器</P></FONT><FONT size=3><P align=justify>break;</P></DIR><P align=justify>case Mplayer::btPrev: //</FONT><FONT face=宋体 size=3>如果用户点击</FONT><FONT size=3>Prev</FONT><FONT face=宋体 size=3>按钮,播放上一首</FONT><FONT size=3>MP3</FONT><FONT face=宋体 size=3>文件</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(false);</P><P align=justify>Query1-&gt;Prior();//</FONT><FONT face=宋体 size=3>使</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的记录光标向前移动一条记录</P></FONT><FONT size=3><P align=justify>if(Query1-&gt;Bof)//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>Bof</FONT><FONT face=宋体 size=3>属性为真,则表示已到了第一个记录</P><DIR><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;Last();//</FONT><FONT face=宋体 size=3>循环到当前数据集的最后一个记录</P></DIR></DIR></FONT><FONT size=3><P align=justify>m_bIsPlaying=true;</P><P align=justify>DoDefault=false;</P><P align=justify>PlayTheSong();</P><P align=justify>Timer1-&gt;Enabled=true;</P></DIR></DIR><P align=justify>break;</P><P align=justify>Timer1</FONT><FONT face=宋体 size=3>的时间事件处理函数如下所示:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::Timer1Timer(TObject *Sender)</P><P align=justify>{</P><P align=justify>if(MediaPlayer1-&gt;Position == MediaPlayer1-&gt;Length) //</FONT><FONT face=宋体 size=3>如果已经播放到一个文件的末尾</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>检测</FONT><FONT size=3>chkLoop</FONT><FONT face=宋体 size=3>是否处于选中状态,以及媒体播放器是否处于播放状态</P></FONT><FONT size=3><P align=justify>if(chkLoop-&gt;Checked &amp;&amp; m_bIsPlaying)</P></FONT><FONT face=宋体 size=3><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;Next();//</FONT><FONT face=宋体 size=3>使</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的记录光标向后移动一条记录</P></FONT><FONT size=3><P align=justify>if(Query1-&gt;Eof)//</FONT><FONT face=宋体 size=3>如果</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT size=3>Eof</FONT><FONT face=宋体 size=3>属性为真,则表示已到了最后一个记录</P><DIR><DIR></FONT><FONT size=3><P align=justify>Query1-&gt;First();//</FONT><FONT face=宋体 size=3>循环到当前数据集的第一个记录</P></DIR></DIR></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>else</P></FONT><FONT face=宋体 size=3><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(true);//</FONT><FONT face=宋体 size=3>使记录操作按钮有效</P></FONT><FONT size=3><P align=justify>Timer1-&gt;Enabled =false;//</FONT><FONT face=宋体 size=3>关闭定时器</P></DIR><P align=justify>}</P></DIR><P align=justify>}</P><P align=justify>}</P><UL><B><P align=justify><LI>添加记录 <p></LI></UL></B></FONT><FONT size=3><P align=justify>TTable</FONT><FONT face=宋体 size=3>控件类提供了两种添加记录的方法,它们是</FONT><FONT size=3>Insert()</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>Append()</FONT><FONT face=宋体 size=3>。其中</FONT><FONT size=3>Insert()</FONT><FONT face=宋体 size=3>方法在当前记录处添加一条新的记录,而</FONT><FONT size=3>Append()</FONT><FONT face=宋体 size=3>则是在数据表的最后添加一条新记录,在</FONT><FONT size=3>MP3Collect</FONT><FONT face=宋体 size=3>中我们要使用的是前者。</P></FONT><FONT size=3><P align=justify>Insert()</FONT><FONT face=宋体 size=3>方法向数据表中添加一条空白的记录,并使</FONT><FONT size=3>Table</FONT><FONT face=宋体 size=3>控件处于记录添加状态。接下来设置新记录的各个字段值,利用</FONT><FONT size=3>TTable</FONT><FONT face=宋体 size=3>类的</FONT><FONT size=3>FieldByName()</FONT><FONT face=宋体 size=3>方法可以获取当前记录的各个字段对象。</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>为字段提供了封装类</FONT><FONT size=3>TField</FONT><FONT face=宋体 size=3>,根据字段不同的数据类型,</FONT><FONT size=3>TField</FONT><FONT face=宋体 size=3>类又提供了</FONT><FONT size=3>As****</FONT><FONT face=宋体 size=3>属性,用于读写其字段值。在</FONT><FONT size=3>MP3Info</FONT><FONT face=宋体 size=3>数据表中,</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>SongName</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>SingerName</FONT><FONT face=宋体 size=3>都是文本类型,因此使用</FONT><FONT size=3>TField</FONT><FONT face=宋体 size=3>类的</FONT><FONT size=3>AsString</FONT><FONT face=宋体 size=3>属性来读写它们的内容。</P><P align=justify>设置好新记录的各个字段值后,需要调用</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Post()</FONT><FONT face=宋体 size=3>方法将此次操作保存到数据库中,如果用户放弃了这次操作,也可以调用</FONT><FONT face="宋体, MS Song" size=3>Cancel()</FONT><FONT face=宋体 size=3>方法取消这次添加操作。</FONT><FONT face="宋体, MS Song" size=3>Post()</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>Cancel()</FONT><FONT face=宋体 size=3>都可以结束记录添加状态,使</FONT><FONT face="宋体, MS Song" size=3>Table</FONT><FONT face=宋体 size=3>控件恢复成记录浏览状态。</P><P align=justify>下面给出“添加”按钮的命令响应函数</FONT><FONT face="宋体, MS Song" size=3>btnAddClick()</FONT><FONT face=宋体 size=3>的新代码,另外一个同时添加多条记录的函数</FONT><FONT face="宋体, MS Song" size=3>mnuAddClick()</FONT><FONT face=宋体 size=3>留给读者朋友自己完成。</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::btnAddClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>if(edtFileName-&gt;Text.IsEmpty())//</FONT><FONT face=宋体 size=3>判断文件名编辑框中是否为空</P><P align=justify>{</P><DIR></FONT><FONT size=3><P align=justify>Application-&gt;MessageBox("</FONT><FONT face=宋体 size=3>文件名称不能为空,请重新输入文件名称!</FONT><FONT size=3>","MP3Collect",MB_OK);</P><P align=justify>edtFileName-&gt;SetFocus();//</FONT><FONT face=宋体 size=3>令文件名编辑框获得键盘输入焦点</P></FONT><FONT size=3><P align=justify>return;</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>Table1-&gt;Insert();//</FONT><FONT face=宋体 size=3>添加一条空白记录</P></FONT><FONT size=3><P align=justify>Table1-&gt;FieldByName("FileName")-&gt;AsString=edtFileName-&gt;Text;//</FONT><FONT face=宋体 size=3>设置</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>字段</P></FONT><FONT size=3><P align=justify>Table1-&gt;FieldByName("SongName")-&gt;AsString=edtSongName-&gt;Text;//</FONT><FONT face=宋体 size=3>设置</FONT><FONT size=3>SongName</FONT><FONT face=宋体 size=3>字段</P></FONT><FONT size=3><P align=justify>Table1-&gt;FieldByName("SingerName")-&gt;AsString=edtSingerName-&gt;Text;//</FONT><FONT face=宋体 size=3>设置</FONT><FONT size=3>SingerName</FONT><FONT face=宋体 size=3>字段</P></FONT><FONT size=3><P align=justify>Table1-&gt;Post();//</FONT><FONT face=宋体 size=3>保存这次添加操作所作的修改</P></FONT><FONT size=3><P align=justify>RefreshQuery();//</FONT><FONT face=宋体 size=3>更新</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件中的数据,同时也更新窗体中的显示</P><P align=justify>}</P><P align=justify>在成功地添加了记录之后,还需要更新窗体上显示的数据,也就是要更新</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件中的数据。由于在进行添加、修改、删除记录等操作之后同样要进行这一步骤,我们为</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>窗体类添加了一个新的成员函数</FONT><FONT face="宋体, MS Song" size=3>RefreshQuery()</FONT><FONT face=宋体 size=3>来完成这一工作。更新</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>的方法比较简单,只需要先关闭一次,再重新打开就可以。为了保证在更新后还能恢复正确的记录光标位置,我们利用了数据集控件的书签对象(</FONT><FONT face="宋体, MS Song" size=3>Bookmark</FONT><FONT face=宋体 size=3>)来保存和恢复记录光标位置。</FONT><FONT face="宋体, MS Song" size=3>RefreshQuery()</FONT><FONT face=宋体 size=3>函数如下所示:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::RefreshQuery()</P><P align=justify>{</P><P align=justify>TBookmark * bm=(TBookmark *)Query1-&gt;GetBookmark();//</FONT><FONT face=宋体 size=3>获取当前</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>控件的书签对象</P></FONT><FONT size=3><P align=justify>Query1-&gt;Close();//</FONT><FONT face=宋体 size=3>先关闭</FONT><FONT size=3>Query1</P><P align=justify>Query1-&gt;Open();//</FONT><FONT face=宋体 size=3>再重新打开</FONT><FONT size=3>Query1</FONT><FONT face=宋体 size=3>,即可更新其中的数据</P></FONT><FONT size=3><P align=justify>Query1-&gt;GotoBookmark(bm);//</FONT><FONT face=宋体 size=3>利用书签对象恢复记录光标的位置</P></FONT><FONT size=3><P align=justify>Query1-&gt;FreeBookmark(bm);//</FONT><FONT face=宋体 size=3>释放书签对象</P><P align=justify>}</P><UL><B><P align=justify><LI>修改记录和删除记录 <p></LI></UL></B><P align=justify>由于前面已经为</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件和</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的光标位置作了同步调整,因此可以保证在</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>中修改和删除的记录是用户当前所选择的记录。</P><P align=justify>修改记录的步骤是:首先调用</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Edit()</FONT><FONT face=宋体 size=3>方法,使其处于记录修改状态,再设置当前记录的各个字段值,设置方法与添加记录中一样,接下来调用</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Post()</FONT><FONT face=宋体 size=3>方法保存这次修改,并关闭记录修改状态,回复到记录浏览状态,最后调用</FONT><FONT face="宋体, MS Song" size=3>RefreshQuery()</FONT><FONT face=宋体 size=3>函数更新显示数据。</P><P align=justify>删除记录的操作最简单,只要调用</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Delete ()</FONT><FONT face=宋体 size=3>方法就可以删除其当前的数据记录。</P><P align=justify>下面是“修改”和“删除”按钮的命令响应函数的实现代码:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::btnModifyClick(TObject *Sender) //</FONT><FONT face=宋体 size=3>“修改”按钮的命令响应函数</P><P align=justify>{</P></FONT><FONT size=3><P align=justify>Table1-&gt;Edit();//</FONT><FONT face=宋体 size=3>使</FONT><FONT size=3>Table1</FONT><FONT face=宋体 size=3>控件处于记录编辑状态</P></FONT><FONT size=3><P align=justify>Table1-&gt;FieldByName("FileName")-&gt;AsString=edtFileName-&gt;Text;//</FONT><FONT face=宋体 size=3>修改</FONT><FONT size=3>FileName</FONT><FONT face=宋体 size=3>字段</P></FONT><FONT size=3><P align=justify>Table1-&gt;FieldByName("SongName")-&gt;AsString=edtSongName-&gt;Text;//</FONT><FONT face=宋体 size=3>修改</FONT><FONT size=3>SongName</FONT><FONT face=宋体 size=3>字段</P></FONT><FONT size=3><P align=justify>Table1-&gt;FieldByName("SingerName")-&gt;AsString=edtSingerName-&gt;Text;//</FONT><FONT face=宋体 size=3>修改</FONT><FONT size=3>SingerName</FONT><FONT face=宋体 size=3>字段</P></FONT><FONT size=3><P align=justify>Table1-&gt;Post();//</FONT><FONT face=宋体 size=3>保存这次操作所作的修改</P></FONT><FONT size=3><P align=justify>RefreshQuery();</P></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::btnDeleteClick(TObject *Sender) //</FONT><FONT face=宋体 size=3>“删除”按钮的命令响应函数</P><P align=justify>{</P></FONT><FONT size=3><P align=justify>Table1-&gt;Delete();//</FONT><FONT face=宋体 size=3>删除当前记录</P></FONT><FONT size=3><P align=justify>RefreshQuery();//</FONT><FONT face=宋体 size=3>更新</FONT><FONT size=3>Query</FONT><FONT face=宋体 size=3>控件中的数据,同时也更新窗体中的显示</P><P align=justify>}</P><P align=justify> </P><P align=justify>到现在为此,我们对</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>的改造也已基本完成,第二版的</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序已经具备了第一版的全部功能,并且解决第一版存在的一些潜在问题。数据库编程其实是一个相当复杂的课题,讲座中介绍的内容仅仅是九牛一毛,读者朋友们必须多学习、多动手实践方可真正掌握好数据库编程。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>实现简单的数据报表</P><FONT face=宋体 size=3>< align=justify>在前两讲中我们已经学习了对数据库进行查询和读写操作的基本方法,本讲中我们将为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>小程序添加另一项与数据库操作有关的新功能:数据报表打印功能。</P>< align=justify>打印数据报表是开发数据库类应用程序过程中经常遇到的问题,特别是在商务类的应用软件中,单位领导或者客户关心的不仅仅是显示在计算机屏幕上的数据,更重要的是打印出来的整齐清晰的报表。</P>< align=justify>设计一个好的数据报表应该遵循这样几个原则:首先要了解用户需要得到什么样的数据,数据库中的记录可能有成千上万条,打印出来的应该是经过提炼、精简的,其中将涉及到数据库的查询、统计、分组、排序等操作;第二个要点是关于报表的布局设计,其设计原则是整齐有序、美观大方,在某些应用场合,如财会类的应用软件中,报表的设计需要遵循固定的格式。第三点是将数据与报表结合起来,实现数据报表的生成与打印。</P><UL><B>< align=justify><LI>使用数据报表向导
8 l, A; g8 L4 ^; |</LI></UL></B>< align=justify>从前面的介绍中我们可以看出,实现数据报表的功能还是颇为复杂的。好在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>充分考虑到了数据报表的重要性,在其集成开发环境中提供了许多现成的数据报表控件,因此大大方便了数据报表的设计与实现。另外,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>还提供有专门的数据报表向导,利用向导可以在几分钟内完成一个简单的数据报表的设计。</P>< align=justify>下面我们首先学习如何使用</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>的数据报表向导。在</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>工程中使用菜单命令“</FONT><FONT face="宋体, MS Song" size=3>File-&gt;New...</FONT><FONT face=宋体 size=3>”,在弹出的新建对象对话框中选择“</FONT><FONT face="宋体, MS Song" size=3>Business</FONT><FONT face=宋体 size=3>”页,并双击其中的“</FONT><FONT face="宋体, MS Song" size=3>Quick Report Wizard</FONT><FONT face=宋体 size=3>”图标。这时会弹出如图</FONT><FONT face="宋体, MS Song" size=3>17-1</FONT><FONT face=宋体 size=3>所示的新数据报表向导对话框,在其中选择报表的样式为“</FONT><FONT face="宋体, MS Song" size=3>List Report</FONT><FONT face=宋体 size=3>”,然后按下“</FONT><FONT face="宋体, MS Song" size=3>Start Wizard</FONT><FONT face=宋体 size=3>”按钮启动向导。</P>< align=justify>向导接下来会显示如图</FONT><FONT face="宋体, MS Song" size=3>17-2</FONT><FONT face=宋体 size=3>所示的参数设置对话框。“</FONT><FONT face="宋体, MS Song" size=3>Alias or directory</FONT><FONT face=宋体 size=3>”一栏用于指定数据库,我们在下拉列表框中选择数据库别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>。“</FONT><FONT face="宋体, MS Song" size=3>Table Name</FONT><FONT face=宋体 size=3>”一栏用于指定表,我们选择</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>。这时,数据表</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>中的四个字段</FONT><FONT face="宋体, MS Song" size=3>ID</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>自动出现在</FONT><FONT face="宋体, MS Song" size=3>Avaliable fields</FONT><FONT face=宋体 size=3>(可用的字段)列表框中,它的右侧是</FONT><FONT face="宋体, MS Song" size=3>Selected fields</FONT><FONT face=宋体 size=3>(选中的字段)列表框,两个列表框中间有四个箭头按钮,用来在两个列表框之间移动字段。在本例中我们只希望打印歌曲名称和歌手名称两项内容,因此将</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>两个字段选入</FONT><FONT face="宋体, MS Song" size=3>Selected fields</FONT><FONT face=宋体 size=3>列表框。设置好显示的数据内容后,按下“</FONT><FONT face="宋体, MS Song" size=3>Finish</FONT><FONT face=宋体 size=3>”按钮,创建报表完毕,这时我们可以看到,工程中新添了一个报表窗体</FONT><FONT face="宋体, MS Song" size=3>Form1</FONT><FONT face=宋体 size=3>,如图</FONT><FONT face="宋体, MS Song" size=3>17-3</FONT><FONT face=宋体 size=3>所示,该窗体上的各个控件的用途及使用方法在下一节中详细介绍。现在我们先来看一下报表窗体运行的效果,用鼠标右键单击窗体中的空白部分,在关联菜单中选择</FONT><FONT face="宋体, MS Song" size=3>review</FONT><FONT face=宋体 size=3>命令,可以对报表进行打印预览,如图</FONT><FONT face="宋体, MS Song" size=3>17-4</FONT><FONT face=宋体 size=3>所示。打印预览是以所见即所得的方式显示报表输出到打印机的效果,在预览窗口的上方有一排快捷按钮,可以进行切换预览方式、浏览不同的页面等操作,其中还有两个打印机形状的按钮,一个用于设置打印机,另一个则是执行打印命令,完成向打印机的输出。预览完毕后可以点击工具条上的</FONT><FONT face="宋体, MS Song" size=3>Close</FONT><FONT face=宋体 size=3>按钮关闭预览窗口。</P>< align=justify>从这个例子中我们可以看出,使用报表向导来创建报表时,只需要指定数据库、数据表、报表中输出的字段名,就可以生成一个简单的数据报表。下面我们就来仔细了解一下报表窗体上的各个组成部分,并在向导生成的报表基础上稍加修改,使之更加满足我们的要求。</P><UL><B>< align=justify><LI>常用的数据报表元件 <p></LI></UL></B>< align=justify>图</FONT><FONT face="宋体, MS Song" size=3>17-3</FONT><FONT face=宋体 size=3>所示的数据报表窗体中,</FONT><FONT face="宋体, MS Song" size=3>TTable</FONT><FONT face=宋体 size=3>控件</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>是我们所熟悉的,它指向</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>数据库中的</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>数据表,其作用是提供打印报表所需要的数据。窗体上的其它控件都属于</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>控件。</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>是由</FONT><FONT face="宋体, MS Song" size=3>QuSoft AS</FONT><FONT face=宋体 size=3>公司开发的第三方软件产品,它以一组元件的形式集成在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中,能够帮助</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>编程人员以可视化的方法快速开发数据报表应用程序,目前</FONT><FONT face="宋体, MS Song" size=3>CBuilder 5.0</FONT><FONT face=宋体 size=3>中采用的是</FONT><FONT face="宋体, MS Song" size=3>QuickReport 3.0</FONT><FONT face=宋体 size=3>版本。</P>< align=justify>在元件面板中找到</FONT><FONT face="宋体, MS Song" size=3>QReport</FONT><FONT face=宋体 size=3>元件栏,我们可以看到其中包含了二十几个元件,利用这些元件,可以使报表输出各种类型的数据,如图像、图形、数值、文本、</FONT><FONT face="宋体, MS Song" size=3>HTML</FONT><FONT face=宋体 size=3>格式的文本等,并控制报表各个部分的输出效果,如大小、字体、颜色、对齐方式等。在设计报表时我们会发现,设计报表和设计程序窗体十分相似,报表中常用的一些元件,如</FONT><FONT face="宋体, MS Song" size=3>TQRLabel</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>TQRMemo</FONT><FONT face=宋体 size=3>等元件与普通的窗体元件如</FONT><FONT face="宋体, MS Song" size=3>TLabel</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>TMemo</FONT><FONT face=宋体 size=3>等在名称和用途上也有一定的对应关系。报表元件与普通窗体元件之间的最重要的差别在于:普通窗体元件具有与用户交互的功能,它们能够接收用户的输入,而报表元件则只是负责输出,输出的结果可能是在打印机上(如果选择了打印报表操作)也可能是在屏幕上(如果选择了打印预览操作)。</P>< align=justify>在</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>元件组中,最重要的元件是</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件,它是实现报表的基础,可以控制报表的生成和打印,它还是其它</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>控件的容器,因此</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>是在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中实现数据报表功能必不可少的控件。在向导生成的</FONT><FONT face="宋体, MS Song" size=3>Form1</FONT><FONT face=宋体 size=3>窗体中,我们可以看到,</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件对象</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>为一个白色背景、带有网格和标尺的矩形。该矩形充满整个窗体的客户区,它代表的是打印输出的纸张大小,</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>内部有一个蓝色虚线的方框,表示可打印区域。在可打印区域内部,我们可以看到用黑色虚线框起的三个长条形区域,每一个长条形区域称为一个</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>。不同的</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>将</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件内部分为不同的区域,例如标题栏区(</FONT><FONT face="宋体, MS Song" size=3>Title</FONT><FONT face=宋体 size=3>)用于显示报表的标题,如果报表由多页组成,则只显示在第一页上;列标题栏区(</FONT><FONT face="宋体, MS Song" size=3>ColumnHeader</FONT><FONT face=宋体 size=3>)显示列标题,如果报表由多页组成,它会显示在每一页的表格上方;明细栏区(</FONT><FONT face="宋体, MS Song" size=3>Detail</FONT><FONT face=宋体 size=3>)则显示具体的数据,虽然在设计阶段只显示了一行内容,但在输出时会根据实际记录的数量显示出多行来,形成一个表格。</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件中定义了六种</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域,除了刚才提到的三种,还有页眉栏(</FONT><FONT face="宋体, MS Song" size=3>ageHeader</FONT><FONT face=宋体 size=3>)、页脚栏(</FONT><FONT face="宋体, MS Song" size=3>ageFooter</FONT><FONT face=宋体 size=3>)、合计栏(</FONT><FONT face="宋体, MS Song" size=3>Summary</FONT><FONT face=宋体 size=3>),</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Bands</FONT><FONT face=宋体 size=3>属性决定了显示哪些</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域。</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件的属性</FONT><FONT face="宋体, MS Song" size=3>DataSet</FONT><FONT face=宋体 size=3>属性决定了它与自己内部的其它报表控件的数据来源。与前两讲介绍的数据访问控件不同的是,数据报表控件可以直接从</FONT><FONT face="宋体, MS Song" size=3>TDataSet</FONT><FONT face=宋体 size=3>类的控件中获取数据,而不需要</FONT><FONT face="宋体, MS Song" size=3>TDataSource</FONT><FONT face=宋体 size=3>控件作为中转。</P>< align=justify>在本例中,</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>DataSet</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>,表示数据来源为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>数据库中的</FONT><FONT face="宋体, MS Song" size=3>MP3Info</FONT><FONT face=宋体 size=3>数据表。除了上述属性之外,</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件的其它重要属性还包括有</FONT><FONT face="宋体, MS Song" size=3>Frame</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>Options</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>age</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>rintSettings</FONT><FONT face=宋体 size=3>等等,其中</FONT><FONT face="宋体, MS Song" size=3>Frame</FONT><FONT face=宋体 size=3>属性定义了报表的四周是否有边框,以及边框的样式(大部分</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>报表控件都有</FONT><FONT face="宋体, MS Song" size=3>Frame</FONT><FONT face=宋体 size=3>属性,用于定义边框),</FONT><FONT face="宋体, MS Song" size=3>Options</FONT><FONT face=宋体 size=3>属性定义了一些用于显示的选项,</FONT><FONT face="宋体, MS Song" size=3>age</FONT><FONT face=宋体 size=3>属性定义了打印纸张的大小、纸型、页边距等,该属性和输出打印机的设置有关,</FONT><FONT face="宋体, MS Song" size=3>rintSettings</FONT><FONT face=宋体 size=3>属性则定义了打印的范围、打印的份数等参数。</P>< align=justify>在</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件中,需要显示的</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域自动显示为</FONT><FONT face="宋体, MS Song" size=3>TQuickRep</FONT><FONT face=宋体 size=3>控件内部的一个黑色虚线矩形,该矩形实际上是一个</FONT><FONT face="宋体, MS Song" size=3>TQRBand</FONT><FONT face=宋体 size=3>控件。</FONT><FONT face="宋体, MS Song" size=3>TQRBand</FONT><FONT face=宋体 size=3>控件封装了报表中不同</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域的属性和方法,其属性</FONT><FONT face="宋体, MS Song" size=3>BandType</FONT><FONT face=宋体 size=3>决定了该</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域的类型。</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>中的三个</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>对象的类型分别为</FONT><FONT face="宋体, MS Song" size=3>rbColumnHeader</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>rbDetail</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>rbPageFooter</FONT><FONT face=宋体 size=3>。</FONT><FONT face="宋体, MS Song" size=3>TQRBand</FONT><FONT face=宋体 size=3>控件可以用来控制各个栏目区域的大小和位置,例如,如果我们加大</FONT><FONT face="宋体, MS Song" size=3>DetailBand1</FONT><FONT face=宋体 size=3>的高度,就可以加大报表表格中行的间距,利用</FONT><FONT face="宋体, MS Song" size=3>TQRBand</FONT><FONT face=宋体 size=3>控件对象还可以实现其它一些显示上的特殊效果,朋友们可以多试一试各种不同设置的效果。不过心铃认为</FONT><FONT face="宋体, MS Song" size=3>TQRBand</FONT><FONT face=宋体 size=3>对象的主要作用应该是作为其它报表控件的容器。</P>< align=justify>前面已经说过,报表</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>被划分为三个</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域,分别是列标题区</FONT><FONT face="宋体, MS Song" size=3>ColumnHeaderBand1</FONT><FONT face=宋体 size=3>、明细区</FONT><FONT face="宋体, MS Song" size=3>DetailBand1</FONT><FONT face=宋体 size=3>和页脚区</FONT><FONT face="宋体, MS Song" size=3>ageFooterBand1</FONT><FONT face=宋体 size=3>。</P>< align=justify>列标题区</FONT><FONT face="宋体, MS Song" size=3>ColumnHeaderBand1</FONT><FONT face=宋体 size=3>内包括两个</FONT><FONT face="宋体, MS Song" size=3>TQRLabel</FONT><FONT face=宋体 size=3>控件,分别显示“</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>”和“</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>”两个字符串。</FONT><FONT face="宋体, MS Song" size=3>TQRLabel</FONT><FONT face=宋体 size=3>控件用于显示固定的文本字符串,它在报表中作用与</FONT><FONT face="宋体, MS Song" size=3>Label</FONT><FONT face=宋体 size=3>控件在普通窗体中的作用是相似的(注意不要在报表中使用普通窗体控件,它们不会在预览或打印结果中显示出来)。</FONT><FONT face="宋体, MS Song" size=3>TQRLabel</FONT><FONT face=宋体 size=3>控件的属性也很好理解,与普通</FONT><FONT face="宋体, MS Song" size=3>Label</FONT><FONT face=宋体 size=3>控件相比,它多了一个</FONT><FONT face="宋体, MS Song" size=3>Frame</FONT><FONT face=宋体 size=3>复合属性,该属性定义了字符串的四周是否显示边框,以及边框的样式等。“</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>”和“</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>”两个</FONT><FONT face="宋体, MS Song" size=3>TQRLabel</FONT><FONT face=宋体 size=3>对象的</FONT><FONT face="宋体, MS Song" size=3>Frame</FONT><FONT face=宋体 size=3>属性中就定义为显示下边框,因此我们在预览效果(图</FONT><FONT face="宋体, MS Song" size=3>17-4</FONT><FONT face=宋体 size=3>)中可以看到列标题下方有一根直线把列标题与报表明细内容区分开来。</P>< align=justify>明细区</FONT><FONT face="宋体, MS Song" size=3>DetailBand1</FONT><FONT face=宋体 size=3>包含两个</FONT><FONT face="宋体, MS Song" size=3>TQRExpr</FONT><FONT face=宋体 size=3>对象</FONT><FONT face="宋体, MS Song" size=3>QRExpr2</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>QRExpr3</FONT><FONT face=宋体 size=3>。</FONT><FONT face="宋体, MS Song" size=3>TQRExpr</FONT><FONT face=宋体 size=3>控件是</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>数据报表特有的控件,它没有普通的窗体控件与之对应,该控件的引入大大方便了数据报表的设计。</FONT><FONT face="宋体, MS Song" size=3>TQRExpr</FONT><FONT face=宋体 size=3>控件的名称从字面上翻译就是数据报表表达式控件,顾名思义,该控件中可以定义一个表达式,输出的是以文本方式显示的表达式结果。该表达式可以由常量(如数字或字符串常量)、数据字段以及</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>支持的一些标准变量(如日期、时间、页码等等)组成,表达式支持的运算包括加、减、乘、除、比较运算、逻辑运算等等,表达式中还支持一些简单的函数调用(如</FONT><FONT face="宋体, MS Song" size=3>SUM()</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>AVERAGE()</FONT><FONT face=宋体 size=3>等等),可见</FONT><FONT face="宋体, MS Song" size=3>TQRExpr</FONT><FONT face=宋体 size=3>控件具有较强的数据处理能力。</P></FONT><FONT size=3>< align=justify>QRExpr2</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>QRExpr3</FONT><FONT face=宋体 size=3>中的表达式比较简单,只定义了要显示的字段名称。如果要构造较为复杂的表达式,可以在对象监视器中双击</FONT><FONT size=3>TQRExpr</FONT><FONT face=宋体 size=3>对象的</FONT><FONT size=3>Expression</FONT><FONT face=宋体 size=3>属性,调出其表达式向导对话框,利用向导构造出符合语法要求的表达式。</P>< align=justify>页脚区</FONT><FONT face="宋体, MS Song" size=3>ageFooterBand1</FONT><FONT face=宋体 size=3>只包含一个</FONT><FONT face="宋体, MS Song" size=3>TQRExpr</FONT><FONT face=宋体 size=3>对象</FONT><FONT face="宋体, MS Song" size=3>QRExpr1</FONT><FONT face=宋体 size=3>,其</FONT><FONT face="宋体, MS Song" size=3>Expression</FONT><FONT face=宋体 size=3>属性字义了它显示的内容为页码数,另外它的</FONT><FONT face="宋体, MS Song" size=3>AlignToBand</FONT><FONT face=宋体 size=3>属性设为了</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>Alignment</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>taRightJustify</FONT><FONT face=宋体 size=3>,表示它将以右对齐的方式显示。</P><UL><B>< align=justify><LI>完成数据报表功能 <p></LI></UL></B><P align=justify>我们已经对数据报表窗体及其上的数据报表控件有了一定的了解,下面我们就来对其报表窗体做一些小小的修改,让它变得美观一些,然后我们在程序的主窗体中加上一些代码,让</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>能够调用数据报表。</P><P align=justify>首先,我们把</FONT><FONT face="宋体, MS Song" size=3>Form1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Name</FONT><FONT face=宋体 size=3>属性改为</FONT><FONT face="宋体, MS Song" size=3>ReportForm</FONT><FONT face=宋体 size=3>,窗体类名称改为</FONT><FONT face="宋体, MS Song" size=3>TReportForm</FONT><FONT face=宋体 size=3>,并将此单元保存为</FONT><FONT face="宋体, MS Song" size=3>Report.cpp</FONT><FONT face=宋体 size=3>(窗体文件与头文件分别保存为</FONT><FONT face="宋体, MS Song" size=3>Report.dfm</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>Report.h</FONT><FONT face=宋体 size=3>)。接下来,我们把</FONT><FONT face="宋体, MS Song" size=3>ReportForm</FONT><FONT face=宋体 size=3>窗体上的</FONT><FONT face="宋体, MS Song" size=3>Table1</FONT><FONT face=宋体 size=3>控件删除,并重新添加一个</FONT><FONT face="宋体, MS Song" size=3>TQuery</FONT><FONT face=宋体 size=3>控件</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Database</FONT><FONT face=宋体 size=3>属性设为别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性为“</FONT><FONT face="宋体, MS Song" size=3>SELECT * FROM MP3Info Order by FileName ASC</FONT><FONT face=宋体 size=3>”。然后指定其</FONT><FONT face="宋体, MS Song" size=3>Active</FONT><FONT face=宋体 size=3>属性为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,其它属性值都接受缺省值。</P><P align=justify>我们把</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>DataSet</FONT><FONT face=宋体 size=3>属性指向新的数据来源</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>,并修改其</FONT><FONT face="宋体, MS Song" size=3>Bands</FONT><FONT face=宋体 size=3>属性,将其中的子属性</FONT><FONT face="宋体, MS Song" size=3>HasTitle</FONT><FONT face=宋体 size=3>设为</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,表示增加报表标题的显示。此时,</FONT><FONT face="宋体, MS Song" size=3>ColumnHeaderBand1</FONT><FONT face=宋体 size=3>前面会自动插入一个新的</FONT><FONT face="宋体, MS Song" size=3>TQRBand</FONT><FONT face=宋体 size=3>控件对象</FONT><FONT face="宋体, MS Song" size=3>TitleBand1</FONT><FONT face=宋体 size=3>,我们将其高度调整到合适的位置,然后在其中添加一个</FONT><FONT face="宋体, MS Song" size=3>TQRLabel</FONT><FONT face=宋体 size=3>控件对象</FONT><FONT face="宋体, MS Song" size=3>QRLabel3</FONT><FONT face=宋体 size=3>,并把</FONT><FONT face="宋体, MS Song" size=3>QRLabel3</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Alignment</FONT><FONT face=宋体 size=3>属性设为</FONT><FONT face="宋体, MS Song" size=3>taCenter</FONT><FONT face=宋体 size=3>,</FONT><FONT face="宋体, MS Song" size=3>AlignToBand</FONT><FONT face=宋体 size=3>属性设为了</FONT><FONT face="宋体, MS Song" size=3>true</FONT><FONT face=宋体 size=3>,表示居中对齐于标题栏的中间,另外还要把</FONT><FONT face="宋体, MS Song" size=3>QRLabel3</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性设为“</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐宝库——查询结果”,字体设置为“宋体”,大小为</FONT><FONT face="宋体, MS Song" size=3>20</FONT><FONT face=宋体 size=3>。</P><P align=justify>接下来我们把</FONT><FONT face="宋体, MS Song" size=3>ColumnHeaderBand1</FONT><FONT face=宋体 size=3>中的</FONT><FONT face="宋体, MS Song" size=3>QRLabel1</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>QRLabel2</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性分别修改为“歌曲名称”和“歌手名称”,并把</FONT><FONT face="宋体, MS Song" size=3>PageFooterBand1</FONT><FONT face=宋体 size=3>中的</FONT><FONT face="宋体, MS Song" size=3>QRExpr1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Expression</FONT><FONT face=宋体 size=3>属性修改为“</FONT><FONT face="宋体, MS Song" size=3>'</FONT><FONT face=宋体 size=3>第</FONT><FONT face="宋体, MS Song" size=3> ' + PageNumber+'</FONT><FONT face=宋体 size=3>页</FONT><FONT face="宋体, MS Song" size=3>'</FONT><FONT face=宋体 size=3>”,把缺省的英文单词改为中文。最后将</FONT><FONT face="宋体, MS Song" size=3>QRLabel1</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>QRLabel2</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>QRExpr1</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>QRExpr2</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>QRExpr3</FONT><FONT face=宋体 size=3>的字体都改为“宋体”,大小改为</FONT><FONT face="宋体, MS Song" size=3>10</FONT><FONT face=宋体 size=3>。在上述过程中,还需要调整各个</FONT><FONT face="宋体, MS Song" size=3>Band</FONT><FONT face=宋体 size=3>区域的高度以适应新的字体高度。</P><P align=justify>做好这一系列调整之后,我们接着要在</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>中添加调用报表窗体的代码。由于</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>窗体上的控件布局已经比较紧凑了,如果再添加新的命令按钮,需要进行的调整就比较大,因此我们不再向</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>窗体中添加新按钮,而是通过添加关联菜单命令的方式来增加打印报表的命令。为此,我们在</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>窗体上的</FONT><FONT face="宋体, MS Song" size=3>PopupMenu1</FONT><FONT face=宋体 size=3>中添加一个菜单项</FONT><FONT face="宋体, MS Song" size=3>mnuReport</FONT><FONT face=宋体 size=3>,其</FONT><FONT face="宋体, MS Song" size=3>Caption</FONT><FONT face=宋体 size=3>属性为“打印报表”,</FONT><FONT face="宋体, MS Song" size=3>OnClick</FONT><FONT face=宋体 size=3>事件处理函数为</FONT><FONT face="宋体, MS Song" size=3>mnuReportClick()</FONT><FONT face=宋体 size=3>,该函数的代码实现如下所示:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::mnuReportClick(TObject *Sender)</P><P align=justify>{</P><P align=justify>ReportForm-&gt;Query1-&gt;Close();</P><P align=justify>ReportForm-&gt;Query1-&gt;SQL-&gt;Clear();</P><P align=justify>ReportForm-&gt;Query1-&gt;SQL-&gt;AddStrings(Query1-&gt;SQL);</P><P align=justify>ReportForm-&gt;Query1-&gt;Open();</P><P align=justify>ReportForm-&gt;QuickRep1-&gt;Preview();</P></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>该函数主要完成以下几个步骤,首先关闭报表窗体的查询控件</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>,清除其中原有的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性,然后将其</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性设置成与主窗体上</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>SQL</FONT><FONT face=宋体 size=3>属性一致,再打开报表窗体的查询控件</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>。这样做的目的是保证报表中显示的数据与主窗体中显示的内容一致。函数最后调用报表窗体上</FONT><FONT face="宋体, MS Song" size=3>QuickRep1</FONT><FONT face=宋体 size=3>控件的</FONT><FONT face="宋体, MS Song" size=3>Preview()</FONT><FONT face=宋体 size=3>方法启动打印预览窗口(如图</FONT><FONT face="宋体, MS Song" size=3>17-5</FONT><FONT face=宋体 size=3>所示),用户在该窗口中就可以完成打印报表的操作。</P><P align=justify> </P><P align=justify>本讲介绍了如何利用</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>控件来实现数据报表的功能,这里介绍的仅仅是最基本的方法,用到的</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>控件也只有少数几个,如果要设计更复杂的数据报表,朋友们还需要进一步学习各种</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>控件的用法。</P><P align=justify> </P><P align=justify> </P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>注册表和动态连接库</P><FONT face=宋体 size=3>< align=justify>前面我们通过例子已经学习了</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>数据库编程的基础知识,本讲我们将学习关于注册表和动态连接库编程方面的知识。</P><UL><B>< align=justify><LI>对注册表编程 . q' n( n' _$ H$ Y/ ]0 ], d: W
</LI></UL></B>< align=justify>应用程序保存信息的常用方法有三种,第一种是保存在文件中,第二种是保存在数据库中,第三种则是保存在系统注册表中。到目前为止,我们已经实践了前面两种方法,下面我们就来看看如何使用注册表。</P>< align=justify>注册表是</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>系统中保存系统配置信息以及应用程序运行参数的地方,注册表也是系统最重要的组成部分之一,如果注册表遭到了破坏,系统功能就会出现混乱,轻则使应用软件不能正确工作,重则会导致系统崩溃。正因为注册表的重要性,使它有一种神秘的色彩,不少参考书上都建议用户不要操作注册表,似乎稍有不慎就会造成巨大损失。其实,对于编程人员来说,注册表可不是什么禁区,相反,它很适合于应用程序保存一些少量的、关键的配置信息。</P>< align=justify>在</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>系统中,我们可以通过</FONT><FONT face="宋体, MS Song" size=3>Regedit.exe</FONT><FONT face=宋体 size=3>(</FONT><FONT face="宋体, MS Song" size=3>Windows 9x</FONT><FONT face=宋体 size=3>)或</FONT><FONT face="宋体, MS Song" size=3>Regedit32.exe</FONT><FONT face=宋体 size=3>(</FONT><FONT face="宋体, MS Song" size=3>Windows NT</FONT><FONT face=宋体 size=3>)来查看和修改注册表中的内容。运行</FONT><FONT face="宋体, MS Song" size=3>Regedit</FONT><FONT face=宋体 size=3>打开注册表,我们可以很清楚地看到,注册表的信息是以树形结构组织在一起的,如图</FONT><FONT face="宋体, MS Song" size=3>18-1</FONT><FONT face=宋体 size=3>,在“我的电脑”下有六个根注册项:</FONT><FONT face="宋体, MS Song" size=3>HKEY_CLASSES_ROOT</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>HKEY_CURRENT_USER</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>HKEY_LOCAL_MACHINE</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>HKEY_USERS</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>HKEY_CURRENT_CONFIG</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>HKEY_DYN_DATA</FONT><FONT face=宋体 size=3>。每个根注册项下面都有数量不等的子注册项,每一个子注册项又称为一个主键,主键的下面还可以有下一层主键,六个根注册项以及不同层次的主键一起形成类似文件目录的树形结构。注册表的每个主键可以定义若干个值,缺省的是默认值,除此之外还可以定义其它关键字的值,值的类型有三种:字符串值、二进制值和</FONT><FONT face="宋体, MS Song" size=3>DWORD</FONT><FONT face=宋体 size=3>型值。</P>< align=justify>下面我们为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序添加注册表读写的功能,把用户输入的查询条件保存在注册表中,即每次启动时自动读取以前在注册表中保存的查询条件,并将满足初始查询条件的记录显示出来,当用户进行一次查找操作时,程序又将新的查询条件写入到注册表中。</P>< align=justify>为了实现这个功能,我们先手工在注册表的</FONT><FONT face="宋体, MS Song" size=3>HKEY_CURRENT_USER</FONT><FONT face=宋体 size=3>根注册项下的</FONT><FONT face="宋体, MS Song" size=3>Software</FONT><FONT face=宋体 size=3>主键下新建一个主键</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,并为该主键创建三个字符串值:</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>。</P></FONT><FONT size=3>< align=justify>CBuilder</FONT><FONT face=宋体 size=3>对注册表的操作主要是通过</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>类</FONT><FONT size=3>TRegistry</FONT><FONT face=宋体 size=3>实现的。使用</FONT><FONT size=3>TRegistry</FONT><FONT face=宋体 size=3>类需要包含头文件</FONT><FONT size=3>Registry.hpp</FONT><FONT face=宋体 size=3>。</FONT><FONT size=3>TRegistry</FONT><FONT face=宋体 size=3>的属性只有五个,分别是</FONT><FONT size=3>Access</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>CurrentKey</FONT><FONT face=宋体 size=3>、 </FONT><FONT size=3>CurrentPath</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>LazyWrite</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>RootKey</FONT><FONT face=宋体 size=3>,其中</FONT><FONT size=3>CurrentKey</FONT><FONT face=宋体 size=3>和</FONT><FONT size=3>CurrentPath</FONT><FONT face=宋体 size=3>是只读属性,分别表示当前主键和当前键所有的路径,另外,</FONT><FONT size=3>Access</FONT><FONT face=宋体 size=3>是访问权限属性,</FONT><FONT size=3>LazyWrite</FONT><FONT face=宋体 size=3>指定进行写操作时真正写入注册表的时间,</FONT><FONT size=3>RootKey</FONT><FONT face=宋体 size=3>属性指定一个根,为后续的操作指定一个注册表子集。</P>< align=justify>使用</FONT><FONT face="宋体, MS Song" size=3>TRegistry</FONT><FONT face=宋体 size=3>类进行注册表操作的一般步骤如下:首先创建一个</FONT><FONT face="宋体, MS Song" size=3>TRegistry</FONT><FONT face=宋体 size=3>对象,然后指定其</FONT><FONT face="宋体, MS Song" size=3>RootKey</FONT><FONT face=宋体 size=3>属性,定义一个有效的子集。接下来利用</FONT><FONT face="宋体, MS Song" size=3>TRegistry::OpenKey</FONT><FONT face=宋体 size=3>方法打开一个注册表主键,该方法以主键的路径作为参数,如果打开成功,就可以进行读写操作。对不同类型的注册表键值,</FONT><FONT face="宋体, MS Song" size=3>TRegistry</FONT><FONT face=宋体 size=3>提供了不同的读写函数,例如读、写字符串值分别使用方法:</FONT><FONT face="宋体, MS Song" size=3>ReadString</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>WriteString</FONT><FONT face=宋体 size=3>。</P>< align=justify>在</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>中,为了实现注册表读写功能,我们要为</FONT><FONT face="宋体, MS Song" size=3>TMainForm</FONT><FONT face=宋体 size=3>类添加两个成员函数</FONT><FONT face="宋体, MS Song" size=3>ReadRegistrys</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>WriteRegistrys</FONT><FONT face=宋体 size=3>。在窗体初始化函数</FONT><FONT face="宋体, MS Song" size=3>FormCreate</FONT><FONT face=宋体 size=3>中调用</FONT><FONT face="宋体, MS Song" size=3>ReadRegistrys</FONT><FONT face=宋体 size=3>,并调用</FONT><FONT face="宋体, MS Song" size=3>btnFindClick</FONT><FONT face=宋体 size=3>函数,使</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件按照所获取的条件进行查询。另外,要在</FONT><FONT face="宋体, MS Song" size=3>btnFindClick</FONT><FONT face=宋体 size=3>函数和</FONT><FONT face="宋体, MS Song" size=3>btnShowAllClick</FONT><FONT face=宋体 size=3>函数中调用</FONT><FONT face="宋体, MS Song" size=3>WriteRegistrys</FONT><FONT face=宋体 size=3>函数将最新的查询条件存入注册表中。</FONT><FONT face="宋体, MS Song" size=3>ReadRegistrys</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>WriteRegistrys</FONT><FONT face=宋体 size=3>函数的实现代码分别如下:</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm::ReadRegistrys() {</P>< align=justify>TRegistry *Registry = new TRegistry; //</FONT><FONT face=宋体 size=3>创建一个</FONT><FONT size=3>TRegistry</FONT><FONT face=宋体 size=3>对象</P></FONT><FONT size=3>< align=justify>Registry-&gt;RootKey=HKEY_CURRENT_USER; //</FONT><FONT face=宋体 size=3>指定</FONT><FONT size=3>TRegistry</FONT><FONT face=宋体 size=3>对象的根</P></FONT><FONT size=3>< align=justify>Registry-&gt;OpenKey("Software\\MP3Collect",TRUE); //</FONT><FONT face=宋体 size=3>打开主键</FONT><FONT size=3>Software\\MP3Collect</P>< align=justify>edtFileName-&gt;Text=Registry-&gt;ReadString("FileName"); //</FONT><FONT face=宋体 size=3>读值</P></FONT><FONT size=3>< align=justify>edtSongName-&gt;Text=Registry-&gt;ReadString("SongName");</P>< align=justify>edtSingerName-&gt;Text=Registry-&gt;ReadString("SingerName");</P>< align=justify>Registry-&gt;CloseKey(); //</FONT><FONT face=宋体 size=3>关闭主键</P></FONT><FONT size=3>< align=justify>delete Registry; //</FONT><FONT face=宋体 size=3>释放对象</P>< align=justify>}</P></FONT><FONT size=3>< align=justify>void __fastcall TMainForm::WriteRegistrys(AnsiString sFileName,AnsiString sSongName,AnsiString sSingerName) {</P>< align=justify>TRegistry *Registry = new TRegistry;</P>< align=justify>Registry-&gt;RootKey=HKEY_CURRENT_USER;</P>< align=justify>Registry-&gt;OpenKey("Software\\MP3Collect",TRUE);</P>< align=justify>Registry-&gt;WriteString("FileName",sFileName);</P>< align=justify>Registry-&gt;WriteString("SongName",sSongName);</P>< align=justify>Registry-&gt;WriteString("SingerName",sSingerName);</P>< align=justify>Registry-&gt;CloseKey();</P>< align=justify>delete Registry;</P></FONT><FONT face=宋体 size=3><P align=justify>}</P><UL><B><P align=justify><LI>动态连接库的特点 <p></LI></UL></B><P align=justify>动态连接库(</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>)是一个包含有函数和数据(资源)的可执行模块,它不能象</FONT><FONT face="宋体, MS Song" size=3>EXE</FONT><FONT face=宋体 size=3>文件那样直接运行,需要由其它可执行模块(一个</FONT><FONT face="宋体, MS Song" size=3>EXE</FONT><FONT face=宋体 size=3>或</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>)在运行时调用它,</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>才会装载它,其中的代码才能被执行,数据才能被引用。</P><P align=justify>在</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中进行编译连接时,程序调用的</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>不会被嵌入到最终的</FONT><FONT face="宋体, MS Song" size=3>EXE</FONT><FONT face=宋体 size=3>文件中,只有在</FONT><FONT face="宋体, MS Song" size=3>EXE</FONT><FONT face=宋体 size=3>文件启动时或运行过程中,</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>的内容才会被动态地加载到内存中,这就是它称为动态连接库的原因。除了动态连接库外,还有静态连接库,这一类的文件在进行连接时,其中的函数和数据会直接嵌入到</FONT><FONT face="宋体, MS Song" size=3>EXE</FONT><FONT face=宋体 size=3>文件中,连接结束后,静态库就成为了</FONT><FONT face="宋体, MS Song" size=3>EXE</FONT><FONT face=宋体 size=3>的一部分,不会再改变,因而称为静态连接库。</P></FONT><FONT size=3><P align=justify>DLL</FONT><FONT face=宋体 size=3>提供了一种应用程序模块化的方法,它可以使得功能模块容易更改和重用。当几个应用程序同时使用一个</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>时,还可以减少系统开销。另外,</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>文件的格式是独立于编程语言的,</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>VC</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>VB</FONT><FONT face=宋体 size=3>开发的</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>库在原则上说是可以互相通用。</P></FONT><FONT size=3><P align=justify>DLL</FONT><FONT face=宋体 size=3>中可以定义两种函数,即导出函数(</FONT><FONT size=3>export</FONT><FONT face=宋体 size=3>)和内部函数(</FONT><FONT size=3>internal</FONT><FONT face=宋体 size=3>)。导出函数可以被其它可执行模块调用,而内部函数只能在</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>内部使用。同样的,</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>中也可以导出全局变量和</FONT><FONT size=3>C++</FONT><FONT face=宋体 size=3>对象。</P><UL><B><P align=justify><LI>创建动态连接库 <p></LI></UL></B><P align=justify>为了学习用</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>编写动态连接库的方法,我们来创建一个可以检查软件使用天数的</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>,如果用户使用软件超过了允许的试用天数,就弹出一个对话框来提醒用户注册软件,然后自动退出。</P><P align=justify>为了完成这一功能,我们可以使用注册表来保存软件的试用信息和软件的运行天数。按照本讲前面介绍的方法,在</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>主键下创建一个</FONT><FONT face="宋体, MS Song" size=3>DWORD</FONT><FONT face=宋体 size=3>类型的键值</FONT><FONT face="宋体, MS Song" size=3>TestUse</FONT><FONT face=宋体 size=3>,它用来表示当前软件是否为试用版,如果是,则该值为</FONT><FONT face="宋体, MS Song" size=3>1</FONT><FONT face=宋体 size=3>,否则为</FONT><FONT face="宋体, MS Song" size=3>0</FONT><FONT face=宋体 size=3>,后面的代码还会在程序第一次运行时自动创建一个二进制值</FONT><FONT face="宋体, MS Song" size=3>BeginTime</FONT><FONT face=宋体 size=3>,用来记录了第一次运行时的日期,我们假定允许用户试用软件</FONT><FONT face="宋体, MS Song" size=3>100</FONT><FONT face=宋体 size=3>天。</P><P align=justify>首先,选择</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中的菜单命令“</FONT><FONT face="宋体, MS Song" size=3>File-&gt;New...</FONT><FONT face=宋体 size=3>”,在弹出的新建对象对话框中选定其中的“</FONT><FONT face="宋体, MS Song" size=3>DLL Wizard</FONT><FONT face=宋体 size=3>”,确定之后会弹出一个</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>向导对话框(图</FONT><FONT face="宋体, MS Song" size=3>18-2</FONT><FONT face=宋体 size=3>),在其中选择源代码类型为</FONT><FONT face="宋体, MS Song" size=3>C++</FONT><FONT face=宋体 size=3>,并且需要使用可视化元件库</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>,然后按下“</FONT><FONT face="宋体, MS Song" size=3>OK</FONT><FONT face=宋体 size=3>”按钮即可。新生成的</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>工程</FONT><FONT face="宋体, MS Song" size=3>Project1</FONT><FONT face=宋体 size=3>中只有一个</FONT><FONT face="宋体, MS Song" size=3>Unit1.cpp</FONT><FONT face=宋体 size=3>文件,其中有一个函数</FONT><FONT face="宋体, MS Song" size=3>DllEntryPoint()</FONT><FONT face=宋体 size=3>,该函数在</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>加载时被调用,相当于应用程序的</FONT><FONT face="宋体, MS Song" size=3>WinMain()</FONT><FONT face=宋体 size=3>函数。我们不对</FONT><FONT face="宋体, MS Song" size=3>DllEntryPoint</FONT><FONT face=宋体 size=3>作任何修改。</P><P align=justify>接下来,再次利用</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>的新建对象对话框创建一个</FONT><FONT face="宋体, MS Song" size=3>AboutBox</FONT><FONT face=宋体 size=3>类型的窗体,并在其上添加有关注册的信息,如图</FONT><FONT face="宋体, MS Song" size=3>18-3</FONT><FONT face=宋体 size=3>所示。该对话框的单元文件被命名为</FONT><FONT face="宋体, MS Song" size=3>Unit2.cpp</FONT><FONT face=宋体 size=3>。</P><P align=justify>下面为这个</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>工程添加导出函数</FONT><FONT face="宋体, MS Song" size=3>CheckFunc()</FONT><FONT face=宋体 size=3>。该函数的声明和定义都位于</FONT><FONT face="宋体, MS Song" size=3>Unit1.cpp</FONT><FONT face=宋体 size=3>中。在导出一个函数时,我们一般采用下面的语法:</P></FONT><FONT size=3><P align=justify>extern “C” __declspec(dllexport) __stdcall </FONT><FONT face=宋体 size=3>函数名称(函数参数)</FONT><FONT size=3>;</P></FONT><FONT face=宋体 size=3><P align=justify>这样的声明方式不仅指明了函数为一个</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>导出函数,而且指明了它的调用规则为</FONT><FONT face="宋体, MS Song" size=3>__stdcall</FONT><FONT face=宋体 size=3>,命名规则为</FONT><FONT face="宋体, MS Song" size=3>C</FONT><FONT face=宋体 size=3>语言。按照</FONT><FONT face="宋体, MS Song" size=3>C</FONT><FONT face=宋体 size=3>语言而不是</FONT><FONT face="宋体, MS Song" size=3>C++</FONT><FONT face=宋体 size=3>来导出函数,可以避免因</FONT><FONT face="宋体, MS Song" size=3>C++</FONT><FONT face=宋体 size=3>名字修饰而造成的不兼容问题。下面是修改后的</FONT><FONT face="宋体, MS Song" size=3>Unit1.cpp</FONT><FONT face=宋体 size=3>的完整代码:</P></FONT><FONT size=3><P align=justify>#include &lt;vcl.h&gt;</P><P align=justify>#include &lt;windows.h&gt;</P><P align=justify>#pragma hdrstop</P><P align=justify>#include &lt;Registry.hpp&gt;</P><P align=justify>USEFORM("Unit2.cpp",AboutBox);</P><P align=justify>#include "unit2.h"</P><P align=justify>extern TAboutBox *AboutBox;</P><P align=justify>#pragma argsused</P><P align=justify>extern "C" __declspec(dllexport) long __stdcall CheckFunc();//</FONT><FONT face=宋体 size=3>声明导出函数</FONT><FONT size=3>CheckFunc</FONT><FONT face=宋体 size=3>()</P></FONT><FONT size=3><P align=justify>int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) //DLL</FONT><FONT face=宋体 size=3>的入口</P><P align=justify>{</FONT><FONT size=3><FONT face="宋体, MS Song"> return 1;}</FONT></P><P align=justify> </P><P align=justify>long __stdcall CheckFunc() { //</FONT><FONT face=宋体 size=3>导出函数</FONT><FONT size=3>CheckFunc</P><P align=justify>TRegistry *Registry =new TRegistry;</P><P align=justify>Registry-&gt;RootKey=HKEY_CURRENT_USER;</P><P align=justify>Registry-&gt;OpenKey("Software\\MP3Collect",TRUE);</P><P align=justify>short bIsTest=Registry-&gt;ReadDword("TestUse");//</FONT><FONT face=宋体 size=3>读入</FONT><FONT size=3>TestUse</FONT><FONT face=宋体 size=3>值,查看本程序是否为试用版本</P></FONT><FONT size=3><P align=justify>TDateTime tNow,tBegin;</P><P align=justify>tNow=TDateTime::CurrentDate();//</FONT><FONT face=宋体 size=3>获取当前日期</P></FONT><FONT size=3><P align=justify>long returnVal=1; //</FONT><FONT face=宋体 size=3>缺省的返回值为</FONT><FONT size=3>1</FONT><FONT face=宋体 size=3>,即没有超过试用期</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>如果为试用版本,则要查看注册表中</FONT><FONT size=3>BeginTime</FONT><FONT face=宋体 size=3>值是否已经存在,如果不存在表示这是程序</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>第一次运行,于是将当前的日期写入注册表中;如果存在则并检查试用期是否已到</P></FONT><FONT size=3><P align=justify>if(bIsTest) {</P><DIR><P align=justify>if(!Registry-&gt;ValueExists("BeginTime"))</P><DIR><P align=justify>Registry-&gt;WriteDate("BeginTime",tNow);</P></DIR><P align=justify>else {</P><DIR><P align=justify>tBegin=Registry-&gt;ReadDate("BeginTime");//</FONT><FONT face=宋体 size=3>读出</FONT><FONT size=3>BeginTime</FONT><FONT face=宋体 size=3>值</P></FONT><FONT size=3><P align=justify>if(tNow&gt;tBegin+100) { //</FONT><FONT face=宋体 size=3>检查是否超过</FONT><FONT size=3>100</FONT><FONT face=宋体 size=3>天试用期</P><DIR><DIR></FONT><FONT size=3><P align=justify>returnVal=0;//</FONT><FONT face=宋体 size=3>超过试用期时的返回值</P></FONT><FONT size=3><P align=justify>AboutBox=new TAboutBox(NULL);//</FONT><FONT face=宋体 size=3>创建并显示注册信息对话框</P></FONT><FONT size=3><P align=justify>AboutBox-&gt;ShowModal();</P><P align=justify>delete AboutBox;</P></DIR></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></DIR><P align=justify>}</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>Registry-&gt;CloseKey();//</FONT><FONT face=宋体 size=3>关闭注册表键</P></FONT><FONT size=3><P align=justify>delete Registry;//</FONT><FONT face=宋体 size=3>释放</FONT><FONT size=3>Registry</FONT><FONT face=宋体 size=3>对象</P></FONT><FONT size=3><P align=justify>return returnVal;//</FONT><FONT face=宋体 size=3>返回检查结果</P><P align=justify>}</P><P align=justify>将修改后的</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>工程</FONT><FONT face="宋体, MS Song" size=3>Project1</FONT><FONT face=宋体 size=3>保存在与</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>工程相同的目录中,然后对</FONT><FONT face="宋体, MS Song" size=3>Project1</FONT><FONT face=宋体 size=3>进行编译、连接,生成的结果是一个动态连接库</FONT><FONT face="宋体, MS Song" size=3>Project1.DLL</FONT><FONT face=宋体 size=3>和它的导入库</FONT><FONT face="宋体, MS Song" size=3>Project1.LIB</FONT><FONT face=宋体 size=3>。</P><UL><B><P align=justify><LI>使用动态连接库 <p></LI></UL></B></FONT><FONT size=3><P align=justify>DLL</FONT><FONT face=宋体 size=3>的导入库中并没有实际代码,只包含有</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>导出函数和数据的相关信息,进行连接时,</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>的连接器需要导入库来定位相关的函数,以便生成</FONT><FONT size=3>EXE</FONT><FONT face=宋体 size=3>文件。通过导入库来使用</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>是一种十分简单方便的办法,其好处在于:编程时可以象调用普通外部函数一样调用从</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>中导入的函数,连接器将完成对</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>导出函数的定位工作,生成的</FONT><FONT size=3>EXE</FONT><FONT face=宋体 size=3>文件在启动时,</FONT><FONT size=3>Windows</FONT><FONT face=宋体 size=3>会自动加载所需要的</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>文件,这种加载方式也称为隐式加载。如果不采用导入库,则需要在程序代码中通过调用</FONT><FONT size=3>LoadLibray</FONT><FONT face=宋体 size=3>函数来显式地加载所需要的</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>模块。</P><P align=justify>下面仍以</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>为例,我们来看看通过导入库使用</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>的方法。前面说过,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>在编辑连接</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>工程时,会自动生成该</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>的导入库</FONT><FONT face="宋体, MS Song" size=3>.LIB</FONT><FONT face=宋体 size=3>文件。如果某个</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>没有相应的</FONT><FONT face="宋体, MS Song" size=3>LIB</FONT><FONT face=宋体 size=3>文件,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>在其</FONT><FONT face="宋体, MS Song" size=3>Bin</FONT><FONT face=宋体 size=3>目录下提供了一个</FONT><FONT face="宋体, MS Song" size=3>IMPLIB.EXE</FONT><FONT face=宋体 size=3>工具,可以为</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>文件生成相应的导入库。</P><P align=justify>打开</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>工程,通过</FONT><FONT face="宋体, MS Song" size=3>View-&gt;Project Manager</FONT><FONT face=宋体 size=3>菜单命令打开其工程管理器,在工程管理器中将导入库</FONT><FONT face="宋体, MS Song" size=3>Project1.LIB</FONT><FONT face=宋体 size=3>文件添加到工程</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>中去。在使用</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>库中的任何函数之前,还需要对引用的函数进行声明,声明语法如下:</P></FONT><FONT size=3><P align=justify>extern “C” __declspec(dllimport) __stdcall </FONT><FONT face=宋体 size=3>函数名称(函数参数)</FONT><FONT size=3>;</P></FONT><FONT face=宋体 size=3><P align=justify>然后就可以象使用普通的外部函数那样使用</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>导出的函数了。</P></FONT><FONT size=3><P align=justify>CheckFunc()</FONT><FONT face=宋体 size=3>函数的声明和调用的代码如下所示:</P></FONT><FONT size=3><P align=justify>extern "C" __declspec(dllimport) long __stdcall CheckFunc();</P><P align=justify>void __fastcall TMainForm::FormCreate(TObject *Sender) {</P><P align=justify>if(CheckFunc()==0){//</FONT><FONT face=宋体 size=3>调用</FONT><FONT size=3>DLL</FONT><FONT face=宋体 size=3>库函数</FONT><FONT size=3>CheckFunc</FONT><FONT face=宋体 size=3>进行试用期检查,如果超过,则退出程序</P><DIR></FONT><FONT size=3><P align=justify>PostMessage(Handle,WM_CLOSE,0,0);</P><P align=justify>return;</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>如果检查正确,则继续其它的初始化工作</P><P align=justify>}</P><P align=justify> </P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>使用<FONT face="宋体, MS Song" size=6>ActiveX</FONT><FONT face=宋体 size=6>控件</P></FONT><FONT face=宋体 size=3>< align=justify>上一讲中我们学习编写和使用</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>的基本方法,</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>实际上是程序模块化和实现代码重用的方式之一,但是由于种种原因,</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>的可重用性并不是最佳的,经常会出现版本冲突问题。为此,微软提出了一种新的</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>编程技术——</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>技术,它可以比</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>更好地解决二进制级的代码重用问题。</P><UL><B>< align=justify><LI>什么是</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件 . j5 N, _( P5 K6 c+ J1 n
</LI></UL></B></FONT><FONT size=3>< align=justify>ActiveX</FONT><FONT face=宋体 size=3>技术是从</FONT><FONT size=3>OLE</FONT><FONT face=宋体 size=3>技术发展而来的。</FONT><FONT size=3>OLE</FONT><FONT face=宋体 size=3>原意是对象链接和嵌入,后来被扩展成为了组件与分布式编程体系结构,并改称为</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>。</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>技术包括有组件对象模型(</FONT><FONT size=3>COM</FONT><FONT face=宋体 size=3>)、进程间编组(</FONT><FONT size=3>Marshaling</FONT><FONT face=宋体 size=3>)、结构化存储(</FONT><FONT size=3>Structured Storage</FONT><FONT face=宋体 size=3>)、对象一致性(</FONT><FONT size=3>Object Persistence</FONT><FONT face=宋体 size=3>)、统一数据传输(</FONT><FONT size=3>Uniform Data Transfer</FONT><FONT face=宋体 size=3>)、自动化(</FONT><FONT size=3>Automation</FONT><FONT face=宋体 size=3>)等等大量内容,其中的核心是组件对象模型</FONT><FONT size=3>COM</FONT><FONT face=宋体 size=3>。</FONT><FONT size=3>COM</FONT><FONT face=宋体 size=3>定义了一种统一的接口调用方式,从而使得</FONT><FONT size=3>COM</FONT><FONT face=宋体 size=3>组件能够独立于编程语言和操作系统平台,并解决了长期困扰软件开发的版本冲突问题。</FONT><FONT size=3>COM</FONT><FONT face=宋体 size=3>非常基础,</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>技术的其它内容都是在它的上面开发出来的。</P></FONT><FONT size=3>< align=justify>ActiveX</FONT><FONT face=宋体 size=3>控件是</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>技术的一种,以前也叫做</FONT><FONT size=3>OLE</FONT><FONT face=宋体 size=3>控件,或者称为</FONT><FONT size=3>OCX</FONT><FONT face=宋体 size=3>控件,这是因为它一般都存放在扩展名为</FONT><FONT size=3>.OCX</FONT><FONT face=宋体 size=3>的文件中。尽管整套</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>技术的理论相当庞大并且非常复杂,但</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>控件使用起来要简单得多,特别是有了在</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>中使用</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>控件的经验和基础,我们会发现</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>控件使用起来与</FONT><FONT size=3>VCL</FONT><FONT face=宋体 size=3>控件十分类似。</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>控件也提供了属性、方法和事件,用于对控件的操作和完成特定的功能,并且一旦将某个</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>控件安装到</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>中后,我们就可以在</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>集成开发环境中方便地使用</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>控件了,元件面板、对象监视器等工具对</FONT><FONT size=3>ActiveX</FONT><FONT face=宋体 size=3>控件都有效。</P>< align=justify>由于</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件为代码提供了良好的封装特性,并且具有良好的对象一致性,使得程序易于升级和保持兼容性,因此不论是商业软件还是共享软件中,</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件应用得都十分广泛。</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件还具有独立于语言、平台和机器的特点,因此它在</FONT><FONT face="宋体, MS Song" size=3>Internet</FONT><FONT face=宋体 size=3>上也得到了广泛的应用。</P>< align=justify>下面我们将对</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序进行一番改造,用</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件</FONT><FONT face="宋体, MS Song" size=3>Windows Media Player</FONT><FONT face=宋体 size=3>代替原来的</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>播放控件</FONT><FONT face="宋体, MS Song" size=3>TMediaPlayer</FONT><FONT face=宋体 size=3>,来学习使用</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件的方法。</P><UL><B>< align=justify><LI>怎样安装</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件 <p></LI></UL></B>< align=justify>我们准备在例子中使用的是微软提供的</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件</FONT><FONT face="宋体, MS Song" size=3>Windows Media Player</FONT><FONT face=宋体 size=3>(后面简称为</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>),该控件集成在</FONT><FONT face="宋体, MS Song" size=3>Win98</FONT><FONT face=宋体 size=3>第二版以上的系统中。需要注意的是,不同版本的</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件的功能稍有不同,特别是最新的</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer 7.0</FONT><FONT face=宋体 size=3>与其它版本在用户界面上有很大区别,为了便于对照讲座学习,心铃建议大家使用</FONT><FONT face="宋体, MS Song" size=3>6.xx</FONT><FONT face=宋体 size=3>版本。从媒体播放器程序的帮助菜单中选择“关于”命令,就可以查看</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件的版本。</P>< align=justify>除了少数几个之外,大部分</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件对</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>来说是属于第三方控件,不能在元件面板上直接找到,因此在使用这些控件之前,必须先把它们安装到</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中。安装步骤如下:</P>< align=justify>首先,选择菜单命令</FONT><FONT face="宋体, MS Song" size=3>Component-&gt;Import ActiveX Control</FONT><FONT face=宋体 size=3>,启动导入</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件对话框(图</FONT><FONT face="宋体, MS Song" size=3>19-1</FONT><FONT face=宋体 size=3>)。该对话框上方的列表框中列出了系统内已注册的所有</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件,在其中找到“</FONT><FONT face="宋体, MS Song" size=3>Windows Media Player</FONT><FONT face=宋体 size=3>”控件并选中它,这时,控件的</FONT><FONT face="宋体, MS Song" size=3>OCX</FONT><FONT face=宋体 size=3>文件名会自动显示在列表框下的文本框中,为</FONT><FONT face="宋体, MS Song" size=3>MSDXM.OCX</FONT><FONT face=宋体 size=3>,而“</FONT><FONT face="宋体, MS Song" size=3>Class name</FONT><FONT face=宋体 size=3>”中显示了要生成的控件类名称,因为缺省给出的类名称与</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>TMediaPlayer</FONT><FONT face=宋体 size=3>控件相冲突,因此我们将其改为</FONT><FONT face="宋体, MS Song" size=3>TWMediaPlayer</FONT><FONT face=宋体 size=3>。“</FONT><FONT face="宋体, MS Song" size=3>alette Page</FONT><FONT face=宋体 size=3>”用于指定安装后的控件显示在元件面板的哪一个元件栏中,我们选择其中的</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>元件栏。“</FONT><FONT face="宋体, MS Song" size=3>Unit dir name</FONT><FONT face=宋体 size=3>”和“</FONT><FONT face="宋体, MS Song" size=3>Search path</FONT><FONT face=宋体 size=3>”是安装控件时所需的路径设置,一般不需要改变,接受缺省值就可以了。确认了上述设置后,按“</FONT><FONT face="宋体, MS Song" size=3>Install...</FONT><FONT face=宋体 size=3>”按钮开始安装。</P>< align=justify>接着</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>会弹出一个对话框,要求我们选择安装新控件的包,我们可以从已有的包工程(</FONT><FONT face="宋体, MS Song" size=3>.bpk</FONT><FONT face=宋体 size=3>文件)中选择一个,也可以新建一个包工程。这里我们接受缺省设置,将</FONT><FONT face="宋体, MS Song" size=3>TWMediaPlayer</FONT><FONT face=宋体 size=3>安装到</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>(该文件是包文件</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpl</FONT><FONT face=宋体 size=3>的工程文件,</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpl</FONT><FONT face=宋体 size=3>是用于包含用户元件的包文件)中,然后按下确定按钮,这时</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>提示需要重建</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>工程,确定后,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>就开始编译连接</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>工程,完成这一过程需要一点时间。如果重建成功,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>会提示“</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpl</FONT><FONT face=宋体 size=3>被重新生成,元件面板中的元件已经更新,</FONT><FONT face="宋体, MS Song" size=3>TWMediaPlayer</FONT><FONT face=宋体 size=3>控件被成功注册”,确定之后,我们会发现</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>当前打开的工程为</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>,应先保存</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>,然后再重新打开原来的</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>工程,我们可以发现元件面板的</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>元件页中新增了</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件的图标。在某些情况下,新增</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件的图标可能没有显示出来,此时我们可以在</FONT><FONT face="宋体, MS Song" size=3>Component</FONT><FONT face=宋体 size=3>菜单中选择</FONT><FONT face="宋体, MS Song" size=3>Install Package</FONT><FONT face=宋体 size=3>命令,并在弹出的对话框中把</FONT><FONT face="宋体, MS Song" size=3>Borland User Components</FONT><FONT face=宋体 size=3>(即</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpl</FONT><FONT face=宋体 size=3>)选中到设计时包文件和运行时包文件中即可。</P>< align=justify>安装好了一个</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件之后,如果用了一段时间又想将它删除应该怎么办呢?一种方法是通过</FONT><FONT face="宋体, MS Song" size=3>Component-&gt;Configure Palette</FONT><FONT face=宋体 size=3>菜单命令,调出元件面板属性对话框并找到相应元件栏的相应控件,通过“</FONT><FONT face="宋体, MS Song" size=3>Hide</FONT><FONT face=宋体 size=3>”按钮将其隐藏起来,以后需要的时候还可以用同样的方法让它重新显示在元件面板上。第二种方法较为彻底,需要修改当初安装控件的包工程。以刚才添加的</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件为例,打开</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>包工程,这时会显示包的工程属性(图</FONT><FONT face="宋体, MS Song" size=3>19-2</FONT><FONT face=宋体 size=3>),我们可以看出文件名中包含了控件名称,如</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer_OCX.cpp</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer_OCX.dcr</FONT><FONT face=宋体 size=3>封装了</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件,我们只需把这两个文件从包工程中删除,然后重新编译生成</FONT><FONT face="宋体, MS Song" size=3>dclusr50.bpk</FONT><FONT face=宋体 size=3>,就可以从包中彻底删除</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件了。</P><UL><B>< align=justify><LI>用</FONT><FONT face="宋体, MS Song" size=3>Windows Media Player</FONT><FONT face=宋体 size=3>控件改造</FONT><FONT size=3><FONT face="宋体, MS Song">MP3Collect </FONT><p></LI></UL></B></FONT><FONT face=宋体 size=3>< align=justify>安装好</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件之后,我们要用它代替原来程序中的</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>元件</FONT><FONT face="宋体, MS Song" size=3>Media Player</FONT><FONT face=宋体 size=3>,来实现播放</FONT><FONT face="宋体, MS Song" size=3>MP3</FONT><FONT face=宋体 size=3>音乐的功能,修改后的</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序如图</FONT><FONT face="宋体, MS Song" size=3>19-3</FONT><FONT face=宋体 size=3>所示。在进行改造之前,心铃建议大家先把原来的工程做一个备份,这样如果在修改过程中出现了错误,容易进行比对查找。</P>< align=justify>我们先把</FONT><FONT face="宋体, MS Song" size=3>MainForm</FONT><FONT face=宋体 size=3>上原有的</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>控件删除,并在空出来的位置上新增加一个</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer1</FONT><FONT face=宋体 size=3>。由于</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件能够播放视频,因此控件上带有视频输出区域,我们需要适当调整控件的大小,使得视频区域隐藏起来。</P>< align=justify>前面说过,当</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件安装成功后,可以象使用普通</FONT><FONT face="宋体, MS Song" size=3>VCL</FONT><FONT face=宋体 size=3>控件一样使用它。但是使用</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件时常会遇到帮助文档不全的问题,特别是从网上下载的一些共享</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件,由于帮助文档很少,常常让人“望</FONT><FONT face="宋体, MS Song" size=3>X</FONT><FONT face=宋体 size=3>兴叹”。心铃在使用</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件时也遇到这个问题,该控件是由微软编写的,</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>中并没有相关的帮助,幸好经过多次搜索后,心铃终于从微软的</FONT><FONT face="宋体, MS Song" size=3>latform SDK</FONT><FONT face=宋体 size=3>中找到了一些帮助,根据这些帮助,心铃在下面的表格中对</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件需要设置的主要属性的大致含义进行了介绍,其中可能会有理解不是十分准确的地方,请朋友们注意这一点。</P><B>< align=center>表19-1:WMediaPlayer1控件主要属性的设置</P></B></FONT><TABLE cellSpacing=1 cellPadding=7 width=607 border=1><TR><TD vAlign=top width="30%"><FONT face=宋体 size=3>< align=justify>属性名称</FONT></P></TD><TD vAlign=top width="12%"><FONT face=宋体 size=3>< align=justify>设置值</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3>< align=justify>解释</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3>< align=justify>AutoRewind</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3>< align=justify>False</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3>< align=justify>禁止播放完毕后自动回到起始点的功能</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3>< align=justify>AutoStart</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3>< align=justify>false</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3>< align=justify>禁止打开文件后自动播放的功能</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3>< align=justify>Mute</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>false</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>取消静音状态</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>PreviewMode</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>false</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>关闭预览模式</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>SendErrorEvents</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>产生错误时发送错误事件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>SendKeyboardEvents</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>用户在控件上按键时发送键盘事件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>SendMouseClickEvents</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>用户在控件上点击鼠标时发送鼠标点击事件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>SendMouseMoveEvents</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>用户在控件上移动鼠标时发送鼠标移动事件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>SendOpenStateChangeEvents</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>打开状态发生变化时发送</FONT><FONT face="宋体, MS Song" size=3>OpenStateChange</FONT><FONT face=宋体 size=3>事件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>SendPlayStateChangeEvents</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>播放状态发生变化时发送</FONT><FONT face="宋体, MS Song" size=3>PlayStateChange</FONT><FONT face=宋体 size=3>事件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowAudioControls</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>显示音量控件</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowControls</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>显示播放控件等</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowDisplay</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>false</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>不显示信息窗口</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowGotoBar</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>false</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>不显示跳转栏</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowHint</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>显示提示信息</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowPositionControls</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>显示向前、向后浏览按钮</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowStatusBar</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>false</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>不显示状态栏</FONT></P></TD></TR><TR><TD vAlign=top width="30%"><FONT size=3><P align=justify>ShowTracker</FONT></P></TD><TD vAlign=top width="12%"><FONT size=3><P align=justify>true</FONT></P></TD><TD vAlign=top width="58%"><FONT face=宋体 size=3><P align=justify>显示播放位置滑动条</FONT></P></TD></TR></TABLE><FONT face=宋体 size=3><P align=justify>设置好控件的属性后,还要对代码进行修改,将原来由</FONT><FONT face="宋体, MS Song" size=3>MediaPlayer1</FONT><FONT face=宋体 size=3>控件实现的功能改为由</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer1</FONT><FONT face=宋体 size=3>实现。</P><P align=justify>用</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件播放一个媒体文件的基本方法是:首先将文件名赋给</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer1</FONT><FONT face=宋体 size=3>的</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>属性,再调用其</FONT><FONT face="宋体, MS Song" size=3>Open</FONT><FONT face=宋体 size=3>方法打开该文件。由于</FONT><FONT face="宋体, MS Song" size=3>Open</FONT><FONT face=宋体 size=3>方法不等待打开成功就会返回,所以不能够马上进行下一步</FONT><FONT face="宋体, MS Song" size=3>Play</FONT><FONT face=宋体 size=3>操作,而需要等待事件</FONT><FONT face="宋体, MS Song" size=3>OnOpenStateChange</FONT><FONT face=宋体 size=3>,在该事件的处理函数中判断文件是否打开正确,如果打开正确,则可以进一步调用其</FONT><FONT face="宋体, MS Song" size=3>Play</FONT><FONT face=宋体 size=3>函数进行播放。下面给出函数</FONT><FONT face="宋体, MS Song" size=3>PlayTheSong</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>OnOpenStateChange</FONT><FONT face=宋体 size=3>事件处理函数的实现代码:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm:layTheSong() </FONT><FONT face=宋体 size=3>{</P></FONT><FONT size=3><P align=justify>WMediaPlayer1-&gt;FileName=DBGrid1-&gt;DataSource-&gt;DataSet-&gt;FieldByName("FileName")-&gt;AsString;</P><P align=justify>WMediaPlayer1-&gt;Open(WMediaPlayer1-&gt;FileName);</P><P align=justify>m_bIsPlaying=true;//</FONT><FONT face=宋体 size=3>设置</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>标志,表示打开成功后进行播放操作</P><P align=justify>}</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::WMediaPlayer1OpenStateChange(TObject *Sender,long bytesSent, long bytesRemaining) </FONT><FONT face=宋体 size=3>{</P></FONT><FONT size=3><P align=justify>//OpenState</FONT><FONT face=宋体 size=3>为</FONT><FONT size=3>6</FONT><FONT face=宋体 size=3>表示打开正确,</FONT><FONT size=3>m_bIsPlaying</FONT><FONT face=宋体 size=3>为真表示下一步应该进行播放操作</P></FONT><FONT size=3><P align=justify>if(WMediaPlayer1-&gt;OpenState==6 &amp;&amp; m_bIsPlaying) {//</FONT><FONT face=宋体 size=3>两个条件同时满足时开始播放。</P><DIR></FONT><FONT size=3><P align=justify>m_bIsPlaying=false;</P><P align=justify>WMediaPlayer1-&gt;Play();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>}</P><P align=justify>在播放过程中,我们还需要根据播放状态的变化将一些命令按钮设置成有效或无效。这一功能在</FONT><FONT face="宋体, MS Song" size=3>OnPlayStateChange</FONT><FONT face=宋体 size=3>事件中完成。播放到文件结尾处时,</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer</FONT><FONT face=宋体 size=3>控件会产生</FONT><FONT face="宋体, MS Song" size=3>OnEndOfStream</FONT><FONT face=宋体 size=3>事件,我们可以在这一事件中判断是否需要循环播放,如果是则播放下一首。</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::WMediaPlayer1PlayStateChange(TObject *Sender, long bytesSent, long bytesRemaining) </FONT><FONT face=宋体 size=3>{</P></FONT><FONT size=3><P align=justify>if(bytesRemaining==2)// bytesRemaining</FONT><FONT face=宋体 size=3>为</FONT><FONT size=3>2</FONT><FONT face=宋体 size=3>表示播放开始</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(false); //</FONT><FONT face=宋体 size=3>使记录操作按钮失效</P></DIR></FONT><FONT size=3><P align=justify>else if(bytesRemaining==0)// bytesRemaining</FONT><FONT face=宋体 size=3>为</FONT><FONT size=3>0</FONT><FONT face=宋体 size=3>表示播放结束</P><DIR></FONT><FONT size=3><P align=justify>EnableButtons(true); //</FONT><FONT face=宋体 size=3>使记录操作按钮失效</P></DIR><P align=justify>}</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm::WMediaPlayer1EndOfStream(TObject *Sender, long bytesTotal) </FONT><FONT face=宋体 size=3>{</P></FONT><FONT size=3><P align=justify>TDataSet * pDS=DBGrid1-&gt;DataSource-&gt;DataSet;</P><P align=justify>if(chkLoop-&gt;Checked){</P><DIR><P align=justify>pDS-&gt;Next();</P><DIR><P align=justify>if(pDS-&gt;Eof) pDS-&gt;First();</P></DIR><P align=justify>PlayTheSong();</P></DIR></FONT><FONT face=宋体 size=3><P align=justify>}</P></FONT><FONT size=3><P align=justify>else EnableButtons(true);</P></FONT><FONT face=宋体 size=3><P align=justify>}</P><P align=justify>当</FONT><FONT face="宋体, MS Song" size=3>Query1</FONT><FONT face=宋体 size=3>控件当前记录发生改变时,在</FONT><FONT face="宋体, MS Song" size=3>WMediaPlayer1</FONT><FONT face=宋体 size=3>中打开相应文件的实现代码如下:</P></FONT><FONT size=3><P align=justify>void __fastcall TMainForm:uery1AfterScroll(TDataSet *DataSet) </FONT><FONT face=宋体 size=3>{</P></FONT><FONT size=3><P align=justify>if(Query1-&gt;State==dsBrowse ) </FONT><FONT face=宋体 size=3>{</P><DIR></FONT><FONT size=3><P align=justify>TDataSet * pDS=DBGrid1-&gt;DataSource-&gt;DataSet ;</P><P align=justify>if(!pDS-&gt;IsEmpty()) </FONT><FONT face=宋体 size=3>{</P><DIR></FONT><FONT size=3><P align=justify>//</FONT><FONT face=宋体 size=3>定位</FONT><FONT size=3>Table1</FONT><FONT face=宋体 size=3>控件,并在编辑框中显示相应的记录信息</P></FONT><FONT size=3><P align=justify>…//</FONT><FONT face=宋体 size=3>(此处同以前的代码,故省略)</P></FONT><FONT size=3><P align=justify>m_bIsPlaying=false;//</FONT><FONT face=宋体 size=3>打开成功后不播放。</P></FONT><FONT size=3><P align=justify>WMediaPlayer1-&gt;FileName =Query1-&gt;FieldByName("FileName")-&gt;AsString;</P><P align=justify>WMediaPlayer1-&gt;Open(WMediaPlayer1-&gt;FileName);//</FONT><FONT face=宋体 size=3>打开媒体文件</P><P align=justify>}</P></DIR></DIR><P align=justify>}</P><P align=justify>}</P><P align=justify> </P><P align=justify>本讲我们学习</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件的基本使用方法,可以说,</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件使用起来并不复杂,但这项技术本身涉及到非常多的概念,朋友们在使用</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件的过程中如果遇到问题,最好多查阅相关资料,特别是开发者提供的开发文档。</P><P align=justify>另外,由于中华网对个人主页服务器进行了调整,心铃原来告诉大家的讲座下载地址有一些变化,请需要电子文档的朋友使用新地址去下载:</FONT><a href="http://ctprwindwind.at.china.com/" target="_blank" ><FONT face="宋体, MS Song" size=3>http://ctprwindwind.at.china.com/</FONT></A><FONT face=宋体 size=3>。</P></FONT>
回复

使用道具 举报

韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

<b><FONT face=宋体 size=6> </FONT></b>< align=center>安装程序的制作</P><FONT face=宋体 size=3>< align=justify>经过前面十九讲的学习,我们已经初步掌握了</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>编程的基本知识,而且亲自动手设计和编写了一个小软件</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,通常一个软件开发完毕后,为了方便用户使用,一般都需要制作相应的安装程序,本讲中我们就来学习如何利用</FONT><FONT face="宋体, MS Song" size=3>InstallShield</FONT><FONT face=宋体 size=3>来制作安装程序。</P><UL></FONT><B><FONT size=3>< align=justify><LI>InstallShield Express</FONT><FONT face=宋体 size=3>简介   Y0 Q* A0 B0 I
</LI></UL></B>< align=justify>要让应用程序在目标机器上顺利运行,除了需要基本的可执行文件之外,还需要一系列支持文件和一个合适的运行环境,其中支持文件包括有程序要调用的动态链接库、控件、相关数据文件等等,运行环境包括注册表配置、数据库配置等等,这些是发布程序时需要配置的几项主要内容。原则上来说,拷贝文件和配置工作都可以通过手工来完成,但这一过程相当复杂,没有用户会喜欢采用这种方式来安装程序,为此,我们需要使用专门的制作安装程序的软件(可简称为“发布软件”)来制作一个使用简便的安装程序,例如</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express</FONT><FONT face=宋体 size=3>。</P></FONT><FONT size=3>< align=justify>InstallShield</FONT><FONT face=宋体 size=3>是一个专业开发发布软件的公司,它为许多著名的编程工具提供了专门的发布软件,如</FONT><FONT size=3>InstallShield For VC</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>InstallShield Express For VB</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>InstallShield Express For CBuilder</FONT><FONT face=宋体 size=3>、</FONT><FONT size=3>InstallShield Express For Delphi</FONT><FONT face=宋体 size=3>等,另外还有通用的</FONT><FONT size=3>InstallShield Express</FONT><FONT face=宋体 size=3>,目前最新版本为</FONT><FONT size=3>3.01</FONT><FONT face=宋体 size=3>,感兴趣的朋友可以到其主页(</FONT><a href="http://www.installshield.com/" target="_blank" ><FONT size=3>http://www.installshield.com</FONT></A><FONT face=宋体 size=3>)去了解最新产品的情况。</P></FONT><FONT size=3>< align=justify>InstallShield Express For CBuilder</FONT><FONT face=宋体 size=3>是</FONT><FONT size=3>InstallShield</FONT><FONT face=宋体 size=3>公司为</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>量身定做的发布软件,随</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>软件包一起发行。不同版本的</FONT><FONT size=3>CBuilder</FONT><FONT face=宋体 size=3>所带的</FONT><FONT size=3>InstallShield Express</FONT><FONT face=宋体 size=3>使用方法很类似而且相互兼容,考虑到不少读者朋友手上的</FONT><FONT size=3>CBuilder 5.0</FONT><FONT face=宋体 size=3>光盘中并没有最新的</FONT><FONT size=3>InstallShield Express For CBuilder 5.0</FONT><FONT face=宋体 size=3>,因此心铃就以</FONT><FONT size=3>InstallShield Express For CBuilder 4.0</FONT><FONT face=宋体 size=3>为例来介绍制作安装程序的过程,不过心铃使用的</FONT><FONT size=3>InstallShield Express For CBuilder 4.0</FONT><FONT face=宋体 size=3>并非企业版,因此功能上有一些限制,但基本上还是能够满足我们的要求。</P><UL><B>< align=justify><LI>创建安装工程 <p></LI></UL></B>< align=justify>由于第</FONT><FONT face="宋体, MS Song" size=3>19</FONT><FONT face=宋体 size=3>讲中的</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>使用了</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件,而</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件的安装比较复杂,</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express for CBuilder 4.0</FONT><FONT face=宋体 size=3>中没有提供简单的方法用于安装</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件,实现起来比较困难。另外,在程序中发布</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件,特别是第三方的</FONT><FONT face="宋体, MS Song" size=3>ActiveX</FONT><FONT face=宋体 size=3>控件时涉及到许可证问题,也比较复杂。因此,下面我们就以第</FONT><FONT face="宋体, MS Song" size=3>19</FONT><FONT face=宋体 size=3>讲以前的</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>为例来制作安装程序。</P>< align=justify>首先运行</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express For CBuilder 4.0</FONT><FONT face=宋体 size=3>,程序启动后会弹出一个对话框,用户可以在其中选择创建一个新的安装程序工程或是打开一个已有的工程,在这里我们选择创建一个新的工程,并在随后的“</FONT><FONT face="宋体, MS Song" size=3>New Project</FONT><FONT face=宋体 size=3>”对话框中输入工程名称</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>和工程路径“</FONT><FONT face="宋体, MS Song" size=3>MP3Collect\MP3CollectSetup</FONT><FONT face=宋体 size=3>”,然后按下“</FONT><FONT face="宋体, MS Song" size=3>Create</FONT><FONT face=宋体 size=3>”按钮,</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express For CBuilder</FONT><FONT face=宋体 size=3>就会在相应的目录下创建一个空白的安装工程。</P><UL><B>< align=justify><LI>设置安装工程参数 <p></LI></UL></B>< align=justify>新工程如图</FONT><FONT face="宋体, MS Song" size=3>20-1</FONT><FONT face=宋体 size=3>所示,实际上是一个安装程序的模板。模板中共分为</FONT><FONT face="宋体, MS Song" size=3>9</FONT><FONT face=宋体 size=3>大项内容,其中前</FONT><FONT face="宋体, MS Song" size=3>6</FONT><FONT face=宋体 size=3>项为参数设置项,包括了发布应用程序涉及到的各个方面的内容。每一大项下面都有若干小选项,单击每个小项左边的箭头按钮可以对该项内容进行设置。新工程中所有设置项目都为初始的缺省值,而用户修改过的项目左边会出现一个红色的“<FONT face="Wingdings 2"></FONT> ”作为标记。</P></FONT><FONT size=3>< align=justify>InstallShield Express For CBuilder</FONT><FONT face=宋体 size=3>采用向导的形式来帮助用户设置安装工程中的各项参数,每一个大项的内容都是一个设置对话框,每一个小项则是对话框中的一个选项页。</P>< align=justify>首先设置“</FONT><FONT face="宋体, MS Song" size=3>Setup the visual Design</FONT><FONT face=宋体 size=3>”,这里主要设置安装程序的外观。</FONT><FONT face="宋体, MS Song" size=3>App Info</FONT><FONT face=宋体 size=3>中可设置要发布软件的名称、版本、公司以及缺省的安装目录,其中,我们将缺省安装目录设为:</FONT><FONT face="宋体, MS Song" size=3>&ltrogramFilesDir&gt;\MP3Collect</FONT><FONT face=宋体 size=3>。这里的“</FONT><FONT face="宋体, MS Song" size=3>&ltrogramFilesDir&gt;</FONT><FONT face=宋体 size=3>”是</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express</FONT><FONT face=宋体 size=3>定义的目录标识符之一,代表目标机器的“</FONT><FONT face="宋体, MS Song" size=3>rogram Files</FONT><FONT face=宋体 size=3>”目录。使用目录标识符可以很好地适应不同系统的差异,让安装程序具有较好的灵活性。常用的目录标识符还有</FONT><FONT face="宋体, MS Song" size=3>&lt;INSTALLDIR&gt;</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>&lt;WINDIR&gt;</FONT><FONT face=宋体 size=3>等等,分别代表目标机器的最终程序安装目录和</FONT><FONT face="宋体, MS Song" size=3>Windows</FONT><FONT face=宋体 size=3>系统所在目录。在</FONT><FONT face="宋体, MS Song" size=3>Main Window</FONT><FONT face=宋体 size=3>选项页中,我们可以指定安装程序主窗口的背景图片、文字,以及</FONT><FONT face="宋体, MS Song" size=3>LOGO</FONT><FONT face=宋体 size=3>图片、背景颜色等。</FONT><FONT face="宋体, MS Song" size=3>Features</FONT><FONT face=宋体 size=3>选项中可以指定是否需要自动卸载功能,我们应将其选中。</P>< align=justify>第二步设置“</FONT><FONT face="宋体, MS Song" size=3>Sepecify InstallShield Objects for Borland C++ Builder</FONT><FONT face=宋体 size=3>”。这一项内容是整个工程设置中的重点,也是专门针对</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>应用程序的特点进行设置的地方。单击其中的某个选项按钮打开设置向导对话框,如图</FONT><FONT face="宋体, MS Song" size=3>20-2</FONT><FONT face=宋体 size=3>所示。在</FONT><FONT face="宋体, MS Song" size=3>General</FONT><FONT face=宋体 size=3>选项页中列出了需要安装的各种对象,如是否安装</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>、是否需要运行时包文件以及安装哪些包文件等。由于</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序使用了</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>进行数据库访问,所以应该选中</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>选项,同时还应该选中</FONT><FONT face="宋体, MS Song" size=3>BDE Control Panel Files</FONT><FONT face=宋体 size=3>选项,该项内容会在目标系统的控制面板中安装</FONT><FONT face="宋体, MS Song" size=3>BDE Administrator</FONT><FONT face=宋体 size=3>,便于管理数据库别名。另外,</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>程序使用了数据库控件和</FONT><FONT face="宋体, MS Song" size=3>QuickReport</FONT><FONT face=宋体 size=3>报表控件,所以还要选中相应的包文件,此外还需要选择“</FONT><FONT face="宋体, MS Song" size=3>Use Packages</FONT><FONT face=宋体 size=3>”、“</FONT><FONT face="宋体, MS Song" size=3>RTL</FONT><FONT face=宋体 size=3>”和“</FONT><FONT face="宋体, MS Song" size=3>Standard VCL Packages</FONT><FONT face=宋体 size=3>”等选项。</P>< align=justify>当我们选中</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>选项时,</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express</FONT><FONT face=宋体 size=3>会自动弹出</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>安装向导,第一步选择</FONT><FONT face="宋体, MS Song" size=3>BDE</FONT><FONT face=宋体 size=3>安装类型,我们在这里选择“完全安装”。第二步决定是否创建数据库别名,因为程序中使用了数据库别名“</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>”,因此在这里也要新建一个别名“</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>”,接着</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express</FONT><FONT face=宋体 size=3>会询问是否要兼容</FONT><FONT face="宋体, MS Song" size=3>16</FONT><FONT face=宋体 size=3>位系统,这里设为不需要。第三步要对别名进行配置,如图</FONT><FONT face="宋体, MS Song" size=3>20-3</FONT><FONT face=宋体 size=3>所示,配置方法是在“</FONT><FONT face="宋体, MS Song" size=3>Alias Name</FONT><FONT face=宋体 size=3>”中选择“</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>”,在“</FONT><FONT face="宋体, MS Song" size=3>ath</FONT><FONT face=宋体 size=3>”中输入别名对应的实际数据库路径名为“</FONT><FONT face="宋体, MS Song" size=3>&lt;INSTALLDIR&gt;\MP3Collect.mdb</FONT><FONT face=宋体 size=3>”,在“</FONT><FONT face="宋体, MS Song" size=3>Type</FONT><FONT face=宋体 size=3>”中选择别名的类型为“</FONT><FONT face="宋体, MS Song" size=3>Microsoft Access Driver(*.mdb)</FONT><FONT face=宋体 size=3>”,图</FONT><FONT face="宋体, MS Song" size=3>20-3</FONT><FONT face=宋体 size=3>最下面一栏用于输入别名的其它参数,参数的格式为“</FONT><FONT face="宋体, MS Song" size=3>Keyname=Value</FONT><FONT face=宋体 size=3>”,各种参数的含义请朋友参考</FONT><FONT face="宋体, MS Song" size=3>BDE Administrator</FONT><FONT face=宋体 size=3>中的别名定义,我们在这里指定一条参数为“</FONT><FONT face="宋体, MS Song" size=3>ODBC DSN=MP3CollectDSN</FONT><FONT face=宋体 size=3>”。</P>< align=justify>到此就完成了对数据库别名的设置,如果以后还需要修改,仍可在图</FONT><FONT face="宋体, MS Song" size=3>20-2</FONT><FONT face=宋体 size=3>所示的对话框中按“</FONT><FONT face="宋体, MS Song" size=3>Settings...</FONT><FONT face=宋体 size=3>”按钮重新设置。</FONT><FONT face="宋体, MS Song" size=3>InstallShield Objects</FONT><FONT face=宋体 size=3>对话框中的</FONT><FONT face="宋体, MS Song" size=3>Advance</FONT><FONT face=宋体 size=3>选项页会根据用户在</FONT><FONT face="宋体, MS Song" size=3>General</FONT><FONT face=宋体 size=3>选项页中所作的选择,自动列出安装相应对象所需要的文件。由于心铃使用的是较早版本的</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express</FONT><FONT face=宋体 size=3>,所以其中列出的许多</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>BPL</FONT><FONT face=宋体 size=3>文件都是</FONT><FONT face="宋体, MS Song" size=3>4.0</FONT><FONT face=宋体 size=3>版本的,还需要在下一个设置中进行修改。</P>< align=justify>第三项设置为“</FONT><FONT face="宋体, MS Song" size=3>Specify Components and Files</FONT><FONT face=宋体 size=3>”。这里有三个选项页。其中主要用到的是</FONT><FONT face="宋体, MS Song" size=3>Groups</FONT><FONT face=宋体 size=3>选项页。</FONT><FONT face="宋体, MS Song" size=3>Groups</FONT><FONT face=宋体 size=3>选项页中将安装到目标机器的所有文件分成了几组(即几个文件夹),如图</FONT><FONT face="宋体, MS Song" size=3>20-4</FONT><FONT face=宋体 size=3>所示。除了</FONT><FONT face="宋体, MS Song" size=3>rogram Files</FONT><FONT face=宋体 size=3>文件夹用来安装应用程序之外,其余几个文件夹是根据前面一步的设置而得到的,我们还可以根据需要增加、删除文件夹和修改文件夹中的文件。</P>< align=justify>首先选中</FONT><FONT face="宋体, MS Song" size=3>rogram Files</FONT><FONT face=宋体 size=3>文件夹,然后利用“</FONT><FONT face="宋体, MS Song" size=3>Insert Files</FONT><FONT face=宋体 size=3>”按钮向其中添加</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.exe</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.mdb</FONT><FONT face=宋体 size=3>。在</FONT><FONT face="宋体, MS Song" size=3>System Files</FONT><FONT face=宋体 size=3>文件夹中,我们要将</FONT><FONT face="宋体, MS Song" size=3>4.0</FONT><FONT face=宋体 size=3>版本的</FONT><FONT face="宋体, MS Song" size=3>DLL</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>BPL</FONT><FONT face=宋体 size=3>文件改成其对应的</FONT><FONT face="宋体, MS Song" size=3>5.0</FONT><FONT face=宋体 size=3>版本库文件,修改后的</FONT><FONT face="宋体, MS Song" size=3>System Files</FONT><FONT face=宋体 size=3>文件夹包括下列文件:</FONT><FONT face="宋体, MS Song" size=3>BORLNDMM.DLL</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>qrpt50.bpl</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>vcl50.bpl</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>vcldb50.bpl</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>vclx50.bpl</FONT><FONT face=宋体 size=3>、</FONT><FONT face="宋体, MS Song" size=3>cc3250mt.dll</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>vclbde50.bpl</FONT><FONT face=宋体 size=3>。其余两个文件夹</FONT><FONT face="宋体, MS Song" size=3>BDE/IDAPI Files</FONT><FONT face=宋体 size=3>和</FONT><FONT face="宋体, MS Song" size=3>BDE/IDAPI CNF File</FONT><FONT face=宋体 size=3>则可以基本不动。选中某个文件夹后,按下“</FONT><FONT face="宋体, MS Song" size=3>roperties</FONT><FONT face=宋体 size=3>”按钮还可以查看和修改每个文件夹的属性,包括名称、文件更新方式和目标平台等,一般接受缺省值即可。</P>< align=justify>第四项设置内容为用户界面设置。</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express</FONT><FONT face=宋体 size=3>将整个安装过程分为几个步骤,每一个步骤有一个用户界面,设置对话框的右边显示了用户界面的预览效果,用户可以选择需要其中的哪几个步骤,并设置其中的一些参数。心铃在其中选择了</FONT><FONT face="宋体, MS Song" size=3>Welcome</FONT><FONT face=宋体 size=3>信息、许可证、选择目录、选择开始菜单文件夹、开始拷贝文件、进度指示以及安装完毕几个步骤。</P>< align=justify>第五项设置注册表。首先在“</FONT><FONT face="宋体, MS Song" size=3>Registry-Keys</FONT><FONT face=宋体 size=3>”选项页中,在</FONT><FONT face="宋体, MS Song" size=3>HKEY_CURRENT_USER</FONT><FONT face=宋体 size=3>下添加一个主键:</FONT><FONT face="宋体, MS Song" size=3>Software\MP3Collect</FONT><FONT face=宋体 size=3>,选中该键后,再在“</FONT><FONT face="宋体, MS Song" size=3>Registry-Values</FONT><FONT face=宋体 size=3>”选项页中添加四个键值“</FONT><FONT face="宋体, MS Song" size=3>FileName</FONT><FONT face=宋体 size=3>”、“</FONT><FONT face="宋体, MS Song" size=3>SongName</FONT><FONT face=宋体 size=3>”、“</FONT><FONT face="宋体, MS Song" size=3>SingerName</FONT><FONT face=宋体 size=3>”和“</FONT><FONT face="宋体, MS Song" size=3>TestUse</FONT><FONT face=宋体 size=3>”,其中前三个为</FONT><FONT face="宋体, MS Song" size=3>String</FONT><FONT face=宋体 size=3>类型,内容为空字符串,第四个为</FONT><FONT face="宋体, MS Song" size=3>DWORD</FONT><FONT face=宋体 size=3>类型,内容为</FONT><FONT face="宋体, MS Song" size=3>1</FONT><FONT face=宋体 size=3>。</P>< align=justify>最后一项设置为“</FONT><FONT face="宋体, MS Song" size=3>Select Folder and Icon</FONT><FONT face=宋体 size=3>”,用于为应用程序在开始菜单中创建一个快捷方式。</FONT><FONT face="宋体, MS Song" size=3>General</FONT><FONT face=宋体 size=3>选项页用指定程序快捷方式的命令参数,我们设置“</FONT><FONT face="宋体, MS Song" size=3>Run Command</FONT><FONT face=宋体 size=3>”为“</FONT><FONT face="宋体, MS Song" size=3>[Program Files]\MP3Collect.exe</FONT><FONT face=宋体 size=3>”。</FONT><FONT face="宋体, MS Song" size=3>Advance</FONT><FONT face=宋体 size=3>选项页用于指定快捷菜单项的位置,我们设置“</FONT><FONT face="宋体, MS Song" size=3>Start In</FONT><FONT face=宋体 size=3>”为“</FONT><FONT face="宋体, MS Song" size=3>[Program Files]</FONT><FONT face=宋体 size=3>”,“</FONT><FONT face="宋体, MS Song" size=3>Icon</FONT><FONT face=宋体 size=3>”为</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.exe</FONT><FONT face=宋体 size=3>的图标,“</FONT><FONT face="宋体, MS Song" size=3>Folder</FONT><FONT face=宋体 size=3>”为“</FONT><FONT face="宋体, MS Song" size=3>rograme Menu Folder</FONT><FONT face=宋体 size=3>”。</P><UL><B><P align=justify><LI>生成安装程序和运行安装程序 <p></LI></UL></B><P align=justify>安装工程中的最后三项用于生成安装程序和进行安装试运行。前面的参数都设置好了之后,可以单击</FONT><FONT face="宋体, MS Song" size=3>Disk Builder</FONT><FONT face=宋体 size=3>制作安装程序。制作前我们可以选择程序发布用的介质,如使用软盘发布可选择</FONT><FONT face="宋体, MS Song" size=3>1.44M</FONT><FONT face=宋体 size=3>,这样制作过程中会自动按照</FONT><FONT face="宋体, MS Song" size=3>1.44M</FONT><FONT face=宋体 size=3>为最大限度制作安装盘。这里我们选择介质类型为</FONT><FONT face="宋体, MS Song" size=3>CD-ROM</FONT><FONT face=宋体 size=3>,让所有安装文件都生成到同一个目录下。选择好介质后按“</FONT><FONT face="宋体, MS Song" size=3>Build</FONT><FONT face=宋体 size=3>”按钮就可以开始制作了,如果制作过程中没有错误,就可以进行下一步工作:测试安装。</P><P align=justify>单击</FONT><FONT face="宋体, MS Song" size=3>Test Run</FONT><FONT face=宋体 size=3>按钮就可以进行测试安装,以检查是否正确。不过根据心铃的经验,由于开发机器上本来就安装有</FONT><FONT face="宋体, MS Song" size=3>CBuilder 5.0</FONT><FONT face=宋体 size=3>,所以一般运行都不会出错,最好在一台没有安装过</FONT><FONT face="宋体, MS Song" size=3>CBuilder 5.0</FONT><FONT face=宋体 size=3>的机器上进行安装测试,这样才能及时发现和解决问题。</P><P align=justify>按照上述步骤生成的安装程序安装到一台新的机器后,还不能马上运行</FONT><FONT face="宋体, MS Song" size=3>MP3Collect.exe</FONT><FONT face=宋体 size=3>,原因是还缺少数据源的配置。由于心铃使用的不是完全版的</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express for CBuilder 4.0</FONT><FONT face=宋体 size=3>,其中缺少自动配置</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源的功能,所以安装完毕后,还要按照第十四讲的方法配置一遍</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源</FONT><FONT face="宋体, MS Song" size=3>MP3CollectDSN</FONT><FONT face=宋体 size=3>,并利用控制面板中的</FONT><FONT face="宋体, MS Song" size=3>BDE Administrator</FONT><FONT face=宋体 size=3>工具重新配置别名</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>,使其指向</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源</FONT><FONT face="宋体, MS Song" size=3>MP3CollectDSN</FONT><FONT face=宋体 size=3>。进行完这个步骤之后,</FONT><FONT face="宋体, MS Song" size=3>MP3Collect</FONT><FONT face=宋体 size=3>才能在目标机器上正常运行。如果朋友们的程序需要配置</FONT><FONT face="宋体, MS Song" size=3>ODBC</FONT><FONT face=宋体 size=3>数据源,建议大家选用</FONT><FONT face="宋体, MS Song" size=3>InstallShield Express 3.01</FONT><FONT face=宋体 size=3>或其它具有配置功能的发布软件。</P><B><P align=justify> </P></B><P align=justify>到现在为止,二十讲的</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>讲座已经结束了,心铃对</FONT><FONT face="宋体, MS Song" size=3>CBuilder</FONT><FONT face=宋体 size=3>也是在不断的学习和探索之中,因此在讲座中难免有各种不足和错误的地方,希望朋友们能够谅解,欢迎大家批评指正,谢谢。</P></FONT>
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2025-5-11 18:06 , Processed in 0.995950 second(s), 96 queries .

回顶部