Searching for Files

To search for files in Delphi, you have to use the TSearchRec record and the following three functions: FindFirst, FindNext, and FindClose. The TSearchRec record and the three functions are declared in the SysUtils unit.

To start searching a directory, you have to call the FindFirst function:

function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec):  Integer;

When calling the FindFirst function to start searching for files, you have to pass both the directory path and the file mask in the Path parameter. Therefore, if you want to find all text files in the root directory of drive C, pass C:\*.txt as the Path parameter.

The Attr parameter enables you to search for additional file types — system files, hidden files, and the like. The following constants, which are also declared in the SysUtils unit, can be passed as the Attr parameter: faReadOnly, faHidden, faSysFile, faDirectory, faArchive, and faAnyFile. There is also an faVolumeID constant, but it's not important anymore and has been marked as deprecated.

When calling both the FindFirst and FindNext functions, you have to pass a TSearchRec variable as the F parameter. Both functions store search results in the F parameter and both functions return 0 if a file was found or an error flag <> 0 if no matching files are found.

When FindFirst returns 0, you can call the FindNext function in a loop to try to find other files that match the given criteria. Finally, you have to call the FindClose function to release the memory allocated by the FindFirst function:

procedure FindClose(var F: TSearchRec);

Listing 18-1 shows how to search for all files in the root directory of drive C.

Listing 18-1: Searching for files

image from book
unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,   Forms, Dialogs, StdCtrls; type   TMainForm = class(TForm)     ListBox1: TListBox;     procedure FormCreate(Sender: TObject);   private     { Private declarations }   public     { Public declarations }   end; var   MainForm: TMainForm; implementation {$R *.dfm} procedure ReadDirectory(const APath: string; AList: TStrings); var   srec: TSearchRec; begin   AList.Clear;   AList.BeginUpdate;   if FindFirst(APath, faAnyFile, srec) = 0 then   try     repeat       AList.Add(srec.Name);     until FindNext(srec) <> 0;   // repeat until error flag   finally     FindClose(srec);   end;                           // try FindFirst   AList.EndUpdate; end; procedure TMainForm.FormCreate(Sender: TObject); begin   ReadDirectory('c:\*.*', ListBox1.Items); end; end.
image from book

Enumerating Available Drives

You can enumerate the available drives by calling either the GetLogicalDrives API function or the GetDriveType API function (both are declared in the Windows unit). The GetLogicalDrives function is a very simple function since it takes no parameters:

function GetLogicalDrives: DWORD; stdcall;

The drawback to the GetLogicalDrives function is that it requires us to know how to check whether a certain bit in the result value is on or off. It returns a bitmask in which the bit at position 0 represents drive A, the bit at position 1 represents drive B, and so on.


The stdcall directive that follows the declaration of the GetLogicalDrives function is a calling convention. Calling conventions determine the order in which parameters are passed to a procedure or a function.

There are several calling conventions in Delphi. The default calling convention is register, which passes parameters from left to right. The default calling convention in the Windows OS, on the other hand, is stdcall, which passes parameters from right to left. Therefore, in order to accept parameters in the correct order, all Windows API functions have to be marked with the stdcall directive.

The EnumerateDrives procedure in Listing 18-2 illustrates how to use the GetLogicalDrives function to enumerate available drives.

Listing 18-2: Enumerating drives with the GetLogicalDrives function

image from book
procedure EnumerateDrives(AList: TStrings); var   Cnt: Integer;   Disks: set of 0..25; begin   AList.Clear;   Integer(Disks) := GetLogicalDrives;   { loop through the Integer result and check each bit }   for Cnt := 0 to 25 do     if Cnt in Disks then       AList.Add(Chr(Cnt + 65) + ':\'); end;
image from book

Code that is much easier to understand can be produced by using the GetDriveType function to enumerate the available drives. The GetDriveType function is actually meant to be used to determine whether a drive is fixed, removable, or other, but it can also be used to enumerate drives.

The GetDriveType function accepts a pointer to a null-terminated string that contains the root directory of the drive we want to check. The string that contains the root directory has to include the backslash: x:\.

function GetDriveType(lpRootPathName: PChar): UINT; stdcall;

When the function succeeds, it returns one of the constants from Table 18-1.

Table 18-1: GetDriveType function results




An unknown drive type.


The root directory doesn't exist.


The drive is removable.


The drive is fixed.


The drive is a network drive.


The drive is a CD-ROM drive.


The drive is a RAM drive.

The EnumerateDrives2 procedure in Listing 18-3 illustrates how to use the GetDriveType function to enumerate available drives.

Listing 18-3: Enumerating drives using the GetDriveType function

image from book
procedure EnumerateDrives2(AList: TStrings); var   c: Char; begin   AList.Clear;   for c in ['A'..'Z'] do     if GetDriveType(PChar(c + ':\')) <> DRIVE_NO_ROOT_DIR then       AList.Add(c + ':\'); end;
image from book

Finally, you can now create a simple directory browser by adding a TCombo- Box component to the Designer Surface and adding the available drives to it in the OnCreate event of the form. You'll also have to set the Style property of the TComboBox component to csDropDownList to enable the user to only select existing items and write an event handler for its OnChange event to browse the root directory of the selected drive (see Figure 18-1):

image from book
Figure 18-1: The Root Directory Browser

procedure TMainForm.FormCreate(Sender: TObject); begin   with ComboBox1 do   begin     EnumerateDrives2(Items);     ItemIndex := Items.IndexOf('C:\');   end;   ReadDirectory('c:\*.*', ListBox1.Items); end; procedure TMainForm.ComboBox1Change(Sender: TObject); begin   ReadDirectory(ComboBox1.Text + '*.*', ListBox1.Items); end;

Inside Delphi 2006
Inside Delphi 2006 (Wordware Delphi Developers Library)
ISBN: 1598220039
EAN: 2147483647
Year: 2004
Pages: 212
Authors: Ivan Hladni © 2008-2017.
If you may any questions please contact us: