VF教程
 

目录操作

 

MkDir :创建当前目录的子目录

ChDir :改变当前目录

GetDir :返回特定磁盘的当前目录

RmDir :删除一个空子目录 

磁盘操作 

DiskFree :返回磁盘自由空间

DiskSize :返回特定磁盘的大小 

文件查找

 

FileSearch :查找目录中是否存在某一特定文件

FindFirst :在目录中查找与给定文件名(可以包含匹配符)及属性集相匹配 的第一个文件

FindNext :返回符合条件的下一个文件

FindClose :中止一个FindFirst / FindNext序列

 

有关文件管理标准过程/函数的更详细资料,请查阅Delphi相关的Help主题。以上的大部分过程在后面都有应用实例,读者可以从中体会其用法。

Delphi的联机帮助Help系统中把有关文件的过程/函数分为两个主题:I/O RoutineFile _Management Routine。前者大部分以文件变量为操作对象,而后者大部分以文件名或文件句柄为操作对象。这里为了方便读者的使用,我们按功能重新进行了分类。在下一节中主要应用I/O Routine主题下的过程,而在第四节的综合举例中主要应用File_Management Routine主题下的过程。

另外,Windows提供了许多有关文件管理的API函数。虽然在一般情况下,利用Delphi提供的函数已足够解决问题,但有时候仍然需要使用Windows API。在(6.4.4.2)中我们就用到了Windows API函数GetDriveType。有关Windows API函数的情况,请读者参阅相关的资料,这里不再进行介绍。

记录文件的应用

 

任务介绍

 

  在这一节,我们开发一个系统安全性综合评估方法管理系统。系统安全性在复杂项目开发中十分重要,但由于牵涉面广因而很难获得客观、全面的评估值。鉴于此我们提出多角度、多侧面评估而后定量集成的思路,并在此基础上提出了多种安全性综合评估方法。每种方法由不同部门进行评估而后把结果汇总、综合。

  为此我们定义如下的记录类型: 

type

TNature = (Micro,Macro);

{方法性质,分为微观和宏观两类} 

   TMethod = Record

Name: string[20]; {方法名}

Condition: string[40]; {方法适用条件}

Nature: TNature; {方法性质}

Result: Real; {方法评估值}

end; 

用来记录不同方法的信息。

  由于不同方法的条件、性质不同,因而对工程开发的不同阶段适用方法集也不同。因此需要根据实际情况对方法集进行管理。我们把每一方法作为一条记录,每一方法集作为一个记录文件。下面讨论系统的实现方法。 

设计基本思路 

  本系统要实现的基本功能是文件的打开、创建、关闭、显示,记录的增加、修改、删除以及结果的综合和显示。为此我们使用了两组按钮分别用于文件和记录的操作, 使用一个StringGrid控件来显示文件内容,使用一个只读编辑框显示结果的综合。

  如图是设计主窗口界面。 

   图6.1 综合评估方法管理系统主窗口界面

 

其中各部件的名称、功能如下表所示:

 

6.1 主窗口部件的设计

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

部件名称 主要属性 备注

──────────────────────────────────────

RecFileForm BorderStyle=bsDialog 文件打开后把文件名附到窗口标题后

Position=poScreenCenter

StringGrid1 大小行数动态确定

HazAttr(编辑框) ReadOnly=True 显示综合结果

OpenButton TabOrder=0 打开一个记录文件,若文件不存在则创建

NewButton Caption='打开' 创建一个记录文件,若文件存在则打开

CloseButton Caption='关闭' 关闭一个已打开的文件

AddButton Caption='增加' 增加一条记录

ModifyButton Caption='修改' 修改一条记录

DeleteButton Caption='删除' 删除一条记录

CalcuButton Caption='计算' 计算最终结果并显示

ExitButton Caption='退出' 系统终止。若当前有打开的文件则先关闭

OpenDialog1 Filter= 选择或输入欲打开的文件

'Record File(*.Rec)|.Rec

|Any File(*.*)|*.*'

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

  另外,StringGrid1HazAttr的标题用两个标签框(Label)来显示。

  另外我们还需要一个编辑对话框。其中四个编辑框NameConditionNature Result分别对应TMethod记录的四个域。 

  

6.2 编辑对话框 

  为协调程序运行,我们定义了一组全局变量。各变量的类型、作用如下表。 

   表6.2 全局变量及其作用

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   变量名 类型 作用

─────────────────────────────────

MethodFile MethodFileType 与当前打开文件相关联的文件变量

FileName string[70] 当前打开文件的文件名

Count Count 当前打开文件的记录总数

CurrentRec Integer 当前处理记录号

FileOpened Boolean 当前是否有文件打开

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

记录文件类型MethodFileType的定义为 

  type

MethodFileType = file of TMethod; 

布尔变量FileOpened用于控制文件按钮的使能、变灰,记录按钮的反应以及系统结束时是否需要首先关闭文件。 

记录文件的打开和创建 

  记录文件的打开和创建同文本文件一样也需要关联和初始化两个步骤。同文本文件唯一的不同是不能使用Append过程。

  记录文件缺省情况下以读写方式打开,如果想以只读或只写方式打开,则需要修改System单元中定义的变量FileMode的值。

  FileMode的取值和意义如下表。 

   表6.3 FileMode的取值和意义

━━━━━━━━━━━━━━

取值 意义

──────────────

0 只读

1 只写

2 读写

━━━━━━━━━━━━━━

 

  FileMode是一个全局变量,对它的每次修改都将影响所有Reset的操作,因此在打开自己的文件后应还原它的值。

  在本系统中,当用户按下“打开”按钮时,首先弹出一个标准文件打开对话框,要求用户输入或选择文件名。确认后如果该文件名的文件存在,则用Reset打开,若不存在则创建。程序清单如下。 

procedure TRecFileForm.OpenButtonClick(Sender: TObject);

begin

if OpenDialog1.Execute then

FileName := OpenDialog1.FileName

else

exit;

AssignFile(MethodFile,Filename);

try

Reset(MethodFile);

FileOpened := True;

except

On EInOutError do

begin

try

if FileExists(FileName) = False then

begin

ReWrite(MethodFile);

FileOpened := True;

end

else

begin

FileOpened := False;

MessageDlg('文件不能打开',mtWarning,[mbOK],0);

end;

except

On EInOutError do

begin

FileOpened := False;

MessageDlg('文件不能创建',mtWarning,[mbOK],0);

end;

end;

end;

end;

if FileOpened = False then exit;

Count := FileSize(MethodFile);

if Count>0 then

ChangeGrid;

RecFileForm.Caption := FormCaption+' -- '+FileName;

NewButton.Enabled := False;

OpenButton.Enabled := False;

CloseButton.Enabled := True;

end;

  首先系统试图用Reset打开一个文件,并置FileOpenedTrue。如果文件不能打开,则引发一个I/O异常。在异常处理过程中,首先检测文件是否存在。若不存在则创建这个文件。否则是其它原因引发的异常,则把FileOpend重置为False 并显示信息“文件不能打开”。在文件创建过程中仍可能引发异常,因而在一个嵌套的异常处理中把FileOpened重置为False,并提示信息“文件不能创建”。

  有关异常处理的内容请读者参看第十二章。这段程序说明:异常处理机制不仅能使我们的程序更健壮,而且为编程提供了灵活性。

  当用户按下“创建”按钮时,系统首先弹出一个标准输入框,要求用户输入文件名,确认后系统首先检测文件是否存在。若存在则直接打开,否则创建一个新文件。打开或创建过程导致异常,则重置FileNameFileOpened两个全局变量。 

procedure TRecFileForm.NewButtonClick(Sender: TObject);
begin

FileName := InputBox('输入框','请输入文件名','');

if FileName = '' then Exit;

try

AssignFile(MethodFile,FileName);

if FileExists(FileName) then

begin

Reset(MethodFile);

Count := FileSize(MethodFile);

if Count>0 then

ChangeGrid;

end

else

begin

Rewrite(MethodFile);

count := 0;

end;

FileOpened := true;

Except

on EInOutError do

begin

FileName := '';

FileOpened := False;

end;

end;

if FileOpened then

begin

NewButton.Enabled := False;

OpenButton.Enabled := False;

CloseButton.Enabled := True;

RecFileForm.Caption := FormCaption+' -- '+FileName;

end;

end; 

  当文件打开或创建后,所要做的工作有:

  ● 若文件非空,则计算文件长度,并用文件内容填充StringGrid1

  ● “创建”、“打开”按钮变灰,“关闭”按钮使能

  ● 把文件名附到窗口标题后

记录文件的读入和显示 

  定义一个全局变量Count用来保存文件中的记录个数。当文件装入时: 

  Count := FileSize(MethodFile) 

  如果Count > 0,则首先确定StringGrid1的高度、行数。为保证StringGrid1不会覆盖窗口下面的编辑框,定义一个常量MaxShow。当Count < MaxShow时,记录可全部显示;当Count >= MaxShow时,StringGrid1自动添加一个滚动棒。为保证滚动棒不覆盖掉显示内容,StringGrid1的宽度应留有余地。

  确定StringGrid1高度、行数的代码如下: 

  With StringGrid do

if count < MaxShow then

Height := DefaultRowHeight * (Count+1)+10

else

Height := DefaultRowHeight * MaxShow+10;

RowCount := Count+1;

end; 

而后从文件中逐个读入记录并显示在StringGrid1的相应位置: 

  for i := 1 to Count do

begin

Read(MethodFile,MethodRec);

ShowMethod(MethodRec,i);

end; 

ShowMehtod是一个过程,用来把一条记录填入StringGrid1的一行中。对于NameCondition域而言,只须直接赋值即可;而对Nature 域需要把枚举类型值转化为对应意义的字符串(0:“微观”,1:“宏观”);而对Result域则需要把数值转化为一定格式的字符串: 

Str (MethodRec.Result:6:4,ResultStr)

  StringGrid1.Cells[3,Pos] := ResultStr; 

Result显示域宽为6,其中小数点后位数为4 

增加一条记录 

  当用户单击“增加”按钮时屏幕将会弹出一个记录编辑模式对话框EditForm。在编辑框中填入合适的内容并按OK键关闭后,相应值写入一个TMethod类型的变量MethodRec中。其中NatureResult 域需要进行转换。之后增加的记录添加到StringGrid1的显示中。

  最后文件定位于尾部,写入当前记录,总记录数加1 

  Seek(MethodFile,Count);

Write(MethodFile,MethodRec);

Count := Count+1; 

完整的程序清单如下: 

procedure TRecFileForm.AddButtonClick(Sender: TObject);

var

MethodRec: TMethod;

Rl: Real;

k: Integer;

EditForm: TEditForm;

begin

if FileOpenEd = False then Exit;

EditForm := TEditForm.Create(self);

if EditForm.ShowModal <> idCancel then

begin

HazAttr.text := '';

MethodRec.Name := EditForm.MethodName.text;

MethodRec.Condition := EditForm.Condition.text;

case EditForm.NatureCombo.ItemIndex of

0:

MethodRec.Nature := Micro;

1:

MethodRec.Nature := Macro ;

end;

Val(EditForm.Result.text,Rl,k);

MethodRec.Result := Rl;

with StringGrid1 do

begin

if Count < MaxShow then

Height := Height+DefaultRowHeight;

RowCount := RowCount+1;

end;

ShowMethod(MethodRec,Count+1);

seek(MethodFile,Count);

write(MethodFile,MethodRec);

Count := Count+1;

end;

end; 

修改记录 

  首先获取当前记录位置: 

  CurrentRec := StringGrid1.Row - 1; 

而后打开编辑对话框并显示当前值。修改完毕后,修改结果保存在一个记录中并在StringGrid1中重新显示。

  最后修改结果写入文件: 

Seek(MethodFile,CurrentRec);

Write(MethodFile,MethodRec); 

完整程序如下: 

procedure TRecFileForm.ModifyButtonClick(Sender: TObject);

var

MethodRec: TMethod;

Rl: Real;

k: Integer;

EditForm: TEditForm;

begin

if FileOpened = False then Exit;

EditForm := TEditForm.Create(self);

CurrentRec := StringGrid1.Row-1;

with EditForm do

begin

MethodName.text := StringGrid1.Cells[0,CurrentRec+1];

Condition.text := StringGrid1.Cells[1,CurrentRec+1];

if StringGrid1.Cells[2,CurrentRec+1] = ' ' then

NatureCombo.ItemIndex := 0

else

NatureCombo.ItemIndex := 1;

Result.text := StringGrid1.Cells[3,CurrentRec+1];

if ShowModal <> idCancel then

begin

HazAttr.text := '';

MethodRec.Name := MethodName.text;

MethodRec.Condition := Condition.text;

case NatureCombo.ItemIndex of

0:

MethodRec.Nature := Micro;

1:

MethodRec.Nature := Macro ;

end;

Val(Result.text,Rl,k);

MethodRec.Result := Rl;

ShowMethod(MethodRec,CurrentRec+1);

seek(MethodFile,CurrentRec);

write(MethodFile,MethodRec);

end;

end;

end;

记录的删除、插入、排序 

  删除一条记录的基本思路是:获取当前记录的位置并把该位置后的记录逐个向前移动。 文件在最后一条记录前截断。 

  for i:=CurrentRec+1 to Count-1 do

begin

seek(MethodFile,i);

read(MethodFile,MethodRec);

seek(MethodFile,i-1);

Write(MethodFile,MethodRec);

end;

Truncate(MethodFile); 

为避免误删除,在进行删除操作前弹出一个消息框进行确认。删除后要更新全局变量的值和显示内容: 

Count := Count - 1;

ChangeGrid; 

完整的程序如下 

procedure TRecFileForm.DeleteButtonClick(Sender: TObject);

var

NewFile: MethodFileType;

MethodRec: TMethod;

NewFileName: String;

i: Integer;

begin

if FileOpened = False then Exit;

CurrentRec := StringGrid1.Row-1;

if CurrentRec < 0 then Exit;

if MessageDlg('Delete Current Record ?', mtConfirmation,

[mbYes, mbNo], 0) = idYes then

begin

HazAttr.text := '';

for I := CurrentRec+1 to Count-1 do

begin

seek(MethodFile,i);

read(MethodFile,MethodRec);

seek(MethodFile,i-1);

Write(MethodFile,MethodRec);

end;

Truncate(MethodFile);

Count := Count-1;

ChangeGrid;

end;

end; 

  这里所显示的删除操作简单明了。但在程序开始设计时我却走了一条弯路,后来发现虽然这种方法用于记录的删除操作显得笨拙、可笑,但却恰恰是记录插入、排序的思想。
  这种思想的核心是创建一个新文件保存更新后的内容。若新文件顺利创建,则删除原文件,否则恢复原来的文件。程序清单如下: 

procedure TRecFileForm.DeleteButtonClick(Sender: TObject);

var

NewFile: MethodFileType;

MethodRec: TMethod;

NewFileName: String;

i: Integer;

begin

if FileOpened = False then Exit;

CurrentRec := StringGrid1.Row-1;

if CurrentRec < 0 then Exit;

if MessageDlg('Delete Current Record ?', mtConfirmation,

[mbYes, mbNo], 0) = idYes then

begin

HazAttr.text := '';

NewFileName := ChangeFileExt(FileName,'.sav');

try

AssignFile(NewFile,FileName);

ReWrite(NewFile);

Except

On EInOutError do

begin

Rename(MethodFile,FileName);

Exit;

end;

end;

for i := 1 to Count do

if I <> CurrentRec+1 then

begin

MethodRec := GridToRec(i);

Write(NewFile,MethodRec);

end;

closeFile(MethodFile);

try

AssignFile(MethodFile,Filename);

Reset(MethodFile);

except

on EInOutError do

begin

DeleteFile(FileName);

AssignFile(MethodFile,NewFileName);

Reset(MethodFile);

Rename(MethodFile,FileName);

Exit;

end;

DeleteFile(NewFileName);

Count:=Count-1;

ChangeGrid;

end;

end; 

  对于记录插入,方法基本同上。对于排序,可先将关键域读入排序,而后再按排序结果对应的记录号顺序重写文件。 

结果综合 

  对不同方法的评估结果,可按一定的公式进行综合。当用户按下“计算”按钮时,系统进行计算并把综合结果写入HazAttr只读编辑框中。

  为保证结果显示的正确性,每次增加、修改、删除操作确认后HazAttr编辑框清空。 

编辑对话框的输入检查 

  当用户单击“增加”或“修改”按钮时系统将弹出一个编辑对话框,让用户输入或修改记录内容。其中的三个编辑框,一个组合列表框分别对应TMethod 的四个域。由于TMethodResult域必须是[0,1]间的小数,因此当用户按OK键关闭对话框时应进行类型和范围检查。

  在VB中我做过同样的工作,那时需要对用户输入的键码逐个进行判断。但这种方法很繁琐、很难做圆满(如不能很好地支持编辑键)。而Object Pascal提供了更好的方法。这种方法的关键就在于它的类型转换函数Val 

procedure Val(Str: String;var V; var Code: Integer) 

  V是由Str转换成的整型或实型数。若字符串非法,则出错位置返至Code;否则置Code0。字符串非法并不会引发一个转换异常。

  如果转换后的数超出了我们的范围,则显式把Code置为-1。最后统一通过检测Code是否为0来判断输入是否合法。

  我们把输入检查放在对话框的OnCloseQuery事件处理过程中。如输入非法,则禁止对话框关闭,并将输入焦点置于Result编辑框中。但假如用户按了Cancel按钮,则这种检查是多余的。为此定义一个布尔变量IsCancel,对话框生成时置为False。假如用户按下Cancel,则置为True,此时OnCloseQuery事件不进行输入检查。

  对话框的OnCloseQuery事件处理过程的程序清单如下: 

procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

var

Res: Real;

k: Integer;

begin

if IsCancel = False then

begin

val(Result.text,Res,k);

if (Res > 1) or (Res < 0) then k := -1;

if k <> 0 then

begin

MessageDlg('非法输入 ',mtWarning,[mbOK],0);

Result.text := '';

CanClose := False;

Result.SetFocus;

end;

end;

end; 

文件和系统的关闭 

  文件关闭须调用CloseFile过程: 

   CloseFile(MethodFile); 

并对系统的状态重新进行设置。

系统关闭时首先检测当前是否有打开的文件。若有则先关闭文件。这在主窗口的OnCloseQuery事件中实现。

实现文件关闭的程序清单如下: 

procedure TRecFileForm.CloseButtonClick(Sender: TObject);

begin

if FileOpened then

begin

CloseFile(MethodFile);

FileOpened := False;

ClearGrid;

OpenButton.Enabled := True;

NewButton.Enabled := True;

CloseButton.Enabled := False;

RecFileForm.Caption := FormCaption;

end;

end; 

实现系统关闭前检查的程序清单如下: 

procedure TRecFileForm.FormCloseQuery(Sender: TObject;

var CanClose: Boolean);

begin

if FileOpened then

closeFile(MethodFile);

end; 

记录文件小结 

  我们所举的例子虽然简单,但基本覆盖了记录文件操作的主要方面。这里关键问题在于灵活应用Delphi提供的文件管理函数。同时,为了保证程序的健壮性应对异常进行捕获并处理。在数据库应用技术发展的今天,记录文件的重要性也许有所下降,但对象我们这里所处理的简单问题它仍有用武之地。

  这里所举的例子一次只能处理一个文件。但读者可以很容易把它改为一个MDI程序。虽然对于这里的实际情况来说,似乎并无必要。 

文件控件的应用 

  Delphi文件管理的最大特色是提供了一组文件操作控件。利用这些控件我们可以快速开发一个文件名浏览系统。其功能强大与其所需书写代码之少所形成的强烈反差,正是Dephi生命力的体现。 

文件控件及其相互关系 

  Delphi提供的专用文件控件如下表所示。 

   表6.4 Delphi专用文件控件

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

控件名 功 能

─────────────────────────────────────

DriveComboBox 驱动器组合列表框。用于选择当前驱动器

FileListBox 文件列表框。用于显示当前目录中的文件和选中当前文件

FilterComboBox 文件类型组合列表框。用于选择显示文件的类型

DirectoryOutline 目录树(6.4节专门介绍)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  以上控件前四个在Component Palette(部件选择板)System页中,DirectoryOutlineComponent PaletteSamples页中。

  以上文件控件再加上文件编辑框、目录标签框(事实上是一般的编辑框、标签框)就可以构成一个完整的文件操作系统。它们之间的联系几乎不用代码支持,只要设置好相应的属性就可以了。

  FileEditDirLabelFileListBoxFileFilterComloList DirectoryListBoxDriveComboList六个控件间的属性联系如下: 

  DriveComboList .DirList := DirectoryListBox;

  DirectoryListBox.DirLabel := DirLabel;

DirectoryListBox.FileList := FileListBox;

FileFilterComboList.FileList := FileListBox;

FileListBox.FileEdit := FileEdit; 

以上联系可以在设计时完成。只要打开相应属性的选择列表框进行选择即可。也可以在运行时利用如上的赋值语句建立联系。

  文件控件的关键属性基本上都在以上联系中反映出来了。除此之外,FileFilterComboList有一个Filter属性,用来设置组合列表框的选择项;FileListBox 有一个Mask属性,用于设置显示文件的类型,这就允许FileListBox在脱离FileFilterComboList单独应用时仍能根据需要显示特定的文件。在6.4节中我们将应用这一功能。

  文件控件的方法、事件基本是从ListBoxComboBox中继承的。但FileListBox 中有一个ApplyFilePath方法很有用,我们将在后边给出其用法。 

文件名浏览查找系统的设计思路 

  作为文件控件的应用实例,我们开发了一个简单的文件名浏览查找系统。这个系统可用于文件名的显示,把选中的文件写入列表框,并能按文件编辑框中输入的通配符对文件进行查找。

 

6.3 文件名浏览查找系统设计主窗口

 

  如图是我们的窗口界面,其中各部件的设计情况如下表所示。 

   表6.5 部件的设计

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

部件 属性 功能

─────────────────────────────────────

FileCtrForm Position=poDefault 主窗口

DirLabel 显示当前目录

FileEdit TabOrder=0 显示当前文件/输入文件显示匹配符

FileListBox1 FileEdit=FileEdit 显示当前目录文件

DirectoryListBox1 DirLabel=DirLabel 显示当前驱动器目录

FileList= FileListBox1

DriveComboBox1 DirList= DirectoryListBox1 选择当前驱动器

FilterComboBox1 FileList=FileListBox1 选择文件显示类型

Filter='All Files(*.*)|*.*|

Source Files(*.pas)|*.pas|

Form Files(*.dfm)|*.dfm|

Project Files(*.dpr)|*.dpr'

ListBox1 显示选中或查找的文件

Button1 Caption='查找' FileEdit 中的内容进行查找

Button2 Caption='退出' 退出系统

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

文件名浏览查找系统的功能和实现 

按指定后缀名显示当前目录中的文件 

  实现这一功能只需要在控件间建立正确的联系即可,不需要代码支持。 

把选中的文件添加到列表框中 

  在FileListBox1OnClick事件中: 

procedure TFileCtrForm.FileListBox1Click(Sender: TObject);

begin

if Searched then

begin

Searched := False;

ListBox1.Items.Clear;

Label5.Caption := 'Selected Files';

end;

if NotInList(ExtractFileName(FileListBox1.FileName),ListBox1.Items) then

ListBox1.Items.Add(ExtractFileName(FileListBox1.FileName));

end; 

  Searched是一个全局变量,用于标明ListBox1当前显示内容是查找的结果还是从FileListBox1中选定的文件。

函数NotInList用于判断待添加的字符串是否已存在于一个TStrings对象中。函数返回一个布尔型变量。

  NotInList的具体实现如下。 

Function TFileCtrForm.NotInList(FileName: String;Items: TStrings): Boolean;

var

i: Integer;

begin

for I := 0 to Items.Count-1 do

if Items[i] = FileName then

begin

NotInList := False;

Exit;

end;

NotInList := True;

end; 

按指定匹配字符串显示当前目录中的文件 

  当在FileEdit中输入一个匹配字符串,并回车,文件列表框将显示匹配结果。这一功能在FileEditOnKeyPress事件中实现。 

procedure TFileCtrForm.FileEditKeyPress(Sender: TObject; var Key: Char);

begin

if Key = #13 then

begin

FileListBox1.ApplyFilePath(FileEdit.Text);

Key := #0;

end;

end; 

  文件列表框提供的ApplyFilePath方法是解决这一问题的关键所在。 

按指定匹配字符串查找当前目录中的文件
  为了进行比较,我们用另一种方法来实现文件的查找功能,即利用标准过程FindFirstFindNext,如图6.4是两种方法的显示结果。FileList1ListBox1 中的内容完全一致。 

 

  图6.4 两种匹配查找方法结果的比较

 

  当用户单击“查找”按钮时,与FileEdit 中字符串相匹配的文件将显示在ListBox1中。下面是实现代码。

 

procedure TFileCtrForm.Button1Click(Sender: TObject);

var

i: Integer;

SearchRec: TSearchRec;

begin

Searched := True;

Label5.Caption := 'Search Result';

ListBox1.Items.Clear;

FindFirst(FileEdit.text,faAnyFile,SearchRec);

ListBox1.Items.Add(SearchRec.Name);

Repeat

i := FindNext(SearchRec);

If i = 0 then

ListBox1.Items.Add(SearchRec.Name);

until i <> 0;

end;

 

  SearchRec是一个TSearchRec类型的记录。TSearchRec的定义如下:

 

TSearchRec = record

Fill: array[1..21] of Byte;

Attr: Byte;

Time: Longint;

Size: Longint;

Name: string[12];

end;

 

  在这一结构中提供了很多信息,灵活应用将给编程带来很大方便。下面我们举几个例子。

  1. 检测给定文件的大小。

 

function GetFileSize(const FileName: String): LongInt;

var

SearchRec: TSearchRec;

begin

if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then

Result := SearchRec.Size

else

Result := -1;

end;

 

这一程序将在下一节中应用。

  2. 获取给定文件的时间戳,事实上等价于FileAge函数。

 

  function GetFileTime(const FileName: String): Longint;

var

SearchRec: TSearchRec;

begin

if FindFirst(ExpandFileName(FileName),faAnyFile, SearchRec) = 0 then

Result := SearchRec.Time

else

Result := -1;

end;

 

3. 检测文件的属性。如果文件具有某种属性,则

 

SearchRec.Attr And GivenAttr > 0

 

属性常量对应的值与意义如下表:

 

   表6.6 属性常量对应的值与意义

━━━━━━━━━━━━━━━━━━━━

常量 值 描述

─────────────────────

faReadOnly $01 只读文件

faHidden $02 隐藏文件

faSysFile $04 系统文件

faVolumeID $08 卷标文件

faDirectory $10 目录文件

faArchive $20 档案文件

faAnyFile $3F 任何文件

上一页 下一页

━━━━━━━━━━━━━━━━━━━━