BCB讲座第十二讲进一步完善应用程序

更新时间:2023-05-20 20:25:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

BCB快速入门与精通

进一步完善应用程序

到上一讲为至,Mp3Collect程序已经具有了记录、编辑、存取文件、查找记录、播放MP3音乐等功能,基本上达到了我们的设计目标,但就操作方便程度而言,Mp3Collect还有所欠缺,因此在本讲中,我们就来为Mp3Collect添加一些辅助功能,使之更加完善。

实现排序功能

为Mp3Collect添加排序功能之后,用户只要用鼠标点击记录列表框的某一列标题头,就可以以该项内容为基础按照字母排列顺序对记录进行排序,如果用户连续两次点击同一列,则可以在升序排列和降序排列之间切换。要实现这个功能,首先需要响应列表框的标题点击事件OnColumnClick,在该事件处理函数中判断是哪一列的标题头被点击,并利用列表框控件的AlphaSort()方法对列表框中的记录进行排序。

AlphaSort()方法可以依据两种标准来进行排序,一是根据列表框控件的SortType属性,该属性支持按照列表项的Caption属性以及Data属性进行排序,而本程序中需要实现对任意一个子列进行排序,不能通过简单地设置SortType属性来实现,因此我们采用第二种方法,即为列表框控件添加OnCompare事件处理函数。添加了OnCompare事件处理函数之后,列表框控件在排序时会自动调用该函数来比较两个列表项的次序,并根据OnCompare返回的结果进行排序。 下面就是ListView1控件的OnColumnClick和OnCompare两个事件的处理函数: //ListView1控件的OnCompare事件处理函数,其中参数Item1和Item2是进行比较的列表项, //通过参数Compare返回比较的结果。

void __fastcall TMainForm::ListView1Compare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &Compare)

{

if (ColumnToSort == 0)//如果ColumnToSort为0,则按列表项Caption属性进行比较 Compare = CompareText(Item1->Caption,Item2->Caption);

else //如果ColumnToSort不为0,计算子列的序号,并按子列项进行比较

{

int ix = ColumnToSort-1;

Compare = CompareText(Item1->SubItems->Strings[ix], Item2->SubItems->Strings[ix]); }

//Tag属性为1时升序排列,为0时降序排列

if(ListView1->Columns->Items[ColumnToSort]->Tag) Compare = -Compare;

}

//ListView1控件的OnColumnClick事件处理函数

void __fastcall TMainForm::ListView1ColumnClick(TObject *Sender, TListColumn *Column) {

//如果是连接点击同一列,则切换该列的升、降序标志,否则记录新的排序列号 if(ColumnToSort==Column->Index) Column->Tag = 1-Column->Tag;

else ColumnToSort = Column->Index;

//调用列表框控件的排序方法

((TCustomListView *)Sender)->AlphaSort();

}

我们在上述代码中使用了TMainForm类的一个新成员变量ColumnToSort,其类型为int,用来

BCB快速入门与精通

存放当前准备排序的列号。另外,为了标志当前应该做升序排列还是降序排列,我们还用到了VCL元件的一个常用属性:Tag,该属性可以在元件对象中保存一个整数值,该属性的意义可以由程序自行进行解释,例如,窗体上有一组相同元件的多个对象时,就可以为各个对象赋予不同的Tag属性值,以此来区分不同的对象。在本程序中,我们就是利用TColumnItem对象(即列标框控件的子列标题)的Tag属性来标志当前应该做升序排列还是降序排列,其初值为0,即缺省操作为降序排列。

获取文件名对话框

大家肯定注意到了,到目前为止,

Mp3Collect主界面上还有两个按钮的

功能未实现,它们分别是“ ”和“退

出”按钮。其中“ ”按钮是为了方

便用户查找和获得文件名称而设计

的,当用户点击该按钮(btnFileName)

时,Mp3Collect就会弹出如图12-1所

示的获取文件名对话框,用户可以在

其中浏览和查找所需要的文件。

图12-1是一个典型的Windows

图12-1:获取文件名对话框

打开文件对话框,Windows 95以上的

操作系统为此功能提供了标准的对话

框,CBuilder的VCL库把该对话框封装成为了OpenDialog控件,在程序中使用起来更为方便。

在第八讲中,我们已经在Mp3Collect的窗体上添加了一个OpenDialog控件,其对象名称为缺省值OpenDialog1,现在我们来设置它的属性。

首先设置其Title属性为“打开一个MP3音

乐”,接下来双击Filter属性,设置文件类型过

滤器。文件类型过滤器是指让对话框在浏览目录

时只显示特定的文件类型,例如,如果我们希望

对话框中只显示MP3音乐文件,就可以设置其

过滤器为“*.MP3”,过滤器标题为“MP3音乐”。

设置过滤器的对话框如图12-2所示,该对话框

允许添加多个过滤器,我们在其中输入想要浏览

的文件类型及相应的扩展名后,按下“OK”按

钮确定所作的设置。除了上述属性之外,

图12-2:设置文件类型过滤器 OpenDialog1控件的其它属性均采用缺省值。

OpenDialog1控件在运行时一般是不可见

的,只有程序调用它的Excute()方法时才会弹出图12-1的对话框,该对话框是模态对话框,即只有关闭对话框后,输入焦点才会回到父窗体中。如果用户选择一个文件并按下“打开”按钮,Excute()方法返回真,如果按“取消”按钮或直接关闭窗口,则Excute()返回假。当Excute()返回真时,通过OpenDialog1控件的FileName属性便可以获得用户选择的文件名。

需要进一步说明的是,OpenDialog控件不仅支持选择单个文件也支持同时选中多个文件,其Options属性中的标志ofAllowMultiSelect可以决定允许单选还是多选。在“ ”按钮启动的浏览功能中,我们采用缺省的单选方式,在本讲的后面,心铃还会介绍OpenDialog控件多选方式的使用方法。

下面是btnFileName按钮的事件处理函数btnFileNameClick:

void __fastcall TMainForm::btnFileNameClick(TObject *Sender)

BCB快速入门与精通

{

if(OpenDialog1->Execute()) //调出打开文件对话框

{

//从OpenDialog1控件的FileName属性中获取用户选择的文件名

//并将获取的文件名赋给edtFileName编辑框

edtFileName->Text=OpenDialog1->FileName;

//把文件名的路径部分和扩展名部分去除,生成缺省的歌曲名称,

edtSongName->Text=ChangeFileExt(ExtractFileName(OpenDialog1->FileName),"");

edtSingerName->Text="";

//在MediaPlayer1控件中打开该文件,可以让用户试听音乐的效果

MediaPlayer1->FileName=OpenDialog1->FileName;

MediaPlayer1->Open();

}

}

实现了文件浏览功能后,程序会出现一个新的问题,就是OpenDialog1对话框在浏览文件时会改变程序的工作目录,随后保存记录文件及读取记录文件时就会到错误的目录下打开文件。

解决这个问题的方法很简单:只要在TMainForm类中添加一个新的成员变量AnsiString m_PathName,并为MainForm窗体添加OnCreate事件处理函数,在其中添加初始化代码m_PathName=GetCurrentDir();然后用成员变量m_PathName代替保存记录文件以及读取记录文件代码中对GetCurrentDir()的调用。

这个问题告诉我们,在程序开发过程中,有时添加一个新功能可能会与已经实现的功能产生冲突,这一方面要求我们认真规划好程序开发的每一步,在程序设计时尽量考虑周到,避免前后矛盾的地方,另一方面说明了测试工作相当重要,只要可能,应在完成一项功能后就测试一项,尽可能早地发现错误并进行改正。

添加右键关联菜单

在使用Windows以及CBuilder集成开发环境的过程

中,我们已经深刻感受到了关联菜单的重要性和灵活性,

下面心铃就来介绍一下如何为Mp3Collect程序添加关联菜

单。

首先在Standard元件栏中找到弹出式菜单控件

(PopupMenu),为窗体添加一个PopupMenu控件,其名

称为PopupMenu1,然后双击PopupMenu1,调出如图12-3

所示的菜单编辑器。

初次打开菜单编辑器时,它会在编辑对象(即

PopupMenu1菜单)中自动生成一个新的菜单项,对象浏

图12-3:菜单编辑器

览器也会自动显示出该菜单项的属性。我们在对象浏览器

中设置新菜单项的Name属性为mnuAdd,Caption属性为

“添加多个记录”,表示用户选择该菜单命令时,可以调用前面讲过的OpenDialog对话框,一次性获取并添加多条MP3文件记录。

设置好一个菜单项并确定后,菜单编辑器会自动生成一个新的菜单项。我们按照同样的方法生成三个新的菜单项,其属性分别为:第二菜单项的Name属性为mnuDelete,Caption属性为“删除”(即删除一条记录);第三菜单项为一个分隔条,设置分隔条的方法很简单,只要将其“Caption”属性设为“-”即可;第四菜单项的Name属性为mnuSort,Caption属性为“排列”。

第四菜单为级联式菜单,即它的下一层还有子菜单。创建子菜单的方法是在菜单编辑器中选中

BCB快速入门与精通

该菜单项,弹出右键关联菜单,并选择其中的“Create SubMenu”命令即可。我们在“排列”的下一层子菜单要添加三个菜单项,它们的Name和Caption属性分别为:mnuSortByFileName(“按文件名”)、mnuSortBySongName(“按歌曲名称”)、mnuSortBySingerName(“按歌手名称”)。

设计好关联菜单控件PopupMenu1,接下来我们要把它与某个控件关联起来。大部分可视的VCL元件都具有PopupMenu属性,利用该属性可以为元件指定一个关联菜单对象,运行时,用户在该元件区域内点击右键,就会弹出相应的关联菜单。按照这一方法,我们将ListView1的PopupMenu属性设为PopupMenu1,即让设计好的弹出式菜单与列表框控件ListView1相关联。

最后要完成菜单命令的事件处理函数,大家应该已经注意到了,PopupMenu1中的菜单命令所完成的大部分功能都已经在前面介绍过了,因此心铃在这里只介绍其中“添加多条记录”菜单命令的实现方法,其余的几个命令处理函数就作为练习由读者朋友自己来完成吧。

我们在菜单编辑器中双击mnuAdd菜单项,由CBuilder自动生成该菜单的命令处理函数mnuAddClick()的框架。该处理函数完成的功能是这样的,首先调出文件浏览对话框,允许用户一次选择多个文件,然后再将这些文件逐条添加到MP3记录集中。下面是mnuAddClick函数的代码。 void __fastcall TMainForm::mnuAddClick(TObject *Sender)

{

int i;

TListItem * newItem;

//设置打开文件对话框的属性,使其能够一次选中多个文件

OpenDialog1->Options.Clear();

OpenDialog1->Options<<ofAllowMultiSelect<< ofFileMustExist<< ofHideReadOnly;

OpenDialog1->Title="选择多个MP3音乐";

if(OpenDialog1->Execute())//运行打开文件对话框,获取多个MP3文件名

{

AnsiString InputString = InputBox("歌手名称", "请输入歌手名称", "");

for(i=0;i<OpenDialog1->Files->Count ;i++)

{

newItem=ListView1->Items->Add();

newItem->Caption = OpenDialog1->Files->Strings[i];

newItem->SubItems->Add(ChangeFileExt(ExtractFileName(

OpenDialog1->Files->Strings[i].c_str()),""));

newItem->SubItems->Add(InputString);

}

SaveFile();

}

//恢复OpenDialog1原来的属性设置

OpenDialog1->Title="打开一个MP3音乐";

OpenDialog1->Options.Clear();

OpenDialog1->Options<< ofFileMustExist<< ofHideReadOnly; //此处“<<”不是移位操作符 }

退出功能

退出功能实现起来非常简单。关闭一个应用程序有很多种方法,它们的原理主要是关闭主窗口或结束消息循环。对Mp3Collect来说,只要关闭主窗体MainForm,就可以退出整个程序的运行。因此在“退出”按钮的事件处理函数中我们只要简单地调用Close()方法就可以了。

BCB快速入门与精通

本讲中我们又为Mp3Collect添加了一些功能,让它使用起来更加方便,同时我们还学习了PopupMenu和OpenDialog两种新控件的使用方法,其实,熟练掌握各种元件的使用方法是学习CBuilder编程的关键点之一,朋友们要想提高CBuilder编程的水平,除了学习讲座中讲解的内容以外,还要自己多做练习,努力用好CBuilder的各种元件。

CBuilder讲座已经过半了,心铃把讲座的电子文档以及第一阶段的源代码上传到了一位朋友的主页上,地址是:,需要的朋友可以去下载,如果有什么问题,欢迎朋友们来信指教。

本文来源:https://www.bwwdw.com/article/st44.html

Top