Monroe406
asked on
Find a file
Rather than reinvent the wheel, I am wondering if there is any source code or component that would perform a function similar to "Start > Find > Files or Folders"? I need a way to present a simple user interface that would allow the user to search for a file wild card, and have any matches listed.
Well if you have D5 you can go to the Component bar and under the Dialogs tab you will find a "Find Dialog" component ready and willing to the the job. :>)
The Crazy One
The Crazy One
You would use FindFirst and FindNext to do this.
First, you declare a variable of type TSearchRec (this will be used to store the search results).
var
SearchRec :TSearchRec;
Then you call FindFirst. The parameters for FindFirst are
function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer;
Pass the filename into Path, the attributes into Attr, and the SearchRec into F.
if (FindFirst('c:\windows\des ktop\*.*', faAnyFile, SearchRec) = ) then
The attributes can be any of all of the following:
faReadOnly $00000001 Read-only files
faHidden $00000002 Hidden files
faSysFile $00000004 System files
faVolumeID $00000008 Volume ID files
faDirectory $00000010 Directory files
faArchive $00000020 Archive files
faAnyFile $0000003F Any file
If you want two or more attributes, you "or" them with each other (or add them).
FindFirst returns 0 if a file is found, otherwise it returns a Windows error code.
Now SearchRec will contain the first instance of the file found.
SearchRec is defined as follows:
TSearchRec = record
Time: Integer;
Size: Integer;
Attr: Integer;
Name: TFileName;
ExcludeAttr: Integer;
FindHandle: THandle;
FindData: TWin32FindData;
end;
You can get any information you need from SearchRec.
To continue looking for more files, call FindNext.
while (FindNext(SearchRec) = 0) do begin
//do something with the searchrec here
end;
FindNext will return 0 every time a file is found again. When it returns a non-zero number, then all of the files have been found (or none of them due to an error).
After this loop, call FindClose.
FindClose(SearchRec)
Here is an example of it all put together. This will put any file (aside from system files) that match the criteria into a StringList.
procedure Find(Filename :TFilename; List :TStringList);
var
SearchRec :TSearchRec;
begin
if (FindFirst(Filename, faAnyFile - faSystemFile, SearchRec) = 0) then begin
List.Add(SearchRec.Name);
while(FindNext(SearchRec) = 0) do
List.Add(SearchRec.Name);
FindClose(SearchRec);
end;
end;
Check in the Delphi help for FindFirst, FindNext, and FindClose for more info.
First, you declare a variable of type TSearchRec (this will be used to store the search results).
var
SearchRec :TSearchRec;
Then you call FindFirst. The parameters for FindFirst are
function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer;
Pass the filename into Path, the attributes into Attr, and the SearchRec into F.
if (FindFirst('c:\windows\des
The attributes can be any of all of the following:
faReadOnly $00000001 Read-only files
faHidden $00000002 Hidden files
faSysFile $00000004 System files
faVolumeID $00000008 Volume ID files
faDirectory $00000010 Directory files
faArchive $00000020 Archive files
faAnyFile $0000003F Any file
If you want two or more attributes, you "or" them with each other (or add them).
FindFirst returns 0 if a file is found, otherwise it returns a Windows error code.
Now SearchRec will contain the first instance of the file found.
SearchRec is defined as follows:
TSearchRec = record
Time: Integer;
Size: Integer;
Attr: Integer;
Name: TFileName;
ExcludeAttr: Integer;
FindHandle: THandle;
FindData: TWin32FindData;
end;
You can get any information you need from SearchRec.
To continue looking for more files, call FindNext.
while (FindNext(SearchRec) = 0) do begin
//do something with the searchrec here
end;
FindNext will return 0 every time a file is found again. When it returns a non-zero number, then all of the files have been found (or none of them due to an error).
After this loop, call FindClose.
FindClose(SearchRec)
Here is an example of it all put together. This will put any file (aside from system files) that match the criteria into a StringList.
procedure Find(Filename :TFilename; List :TStringList);
var
SearchRec :TSearchRec;
begin
if (FindFirst(Filename, faAnyFile - faSystemFile, SearchRec) = 0) then begin
List.Add(SearchRec.Name);
while(FindNext(SearchRec) = 0) do
List.Add(SearchRec.Name);
FindClose(SearchRec);
end;
end;
Check in the Delphi help for FindFirst, FindNext, and FindClose for more info.
Oops sorry misread the question. :>)
edey: forgive me, didn't see your post when I posted this
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
E-E is not "thread safe" =)
ASKER
>> You would use FindFirst and FindNext to do this.
Thanks "scrapdog", but your sample does not iterate through subfolders.
Thanks "scrapdog", but your sample does not iterate through subfolders.
ASKER
>> while sr = 0 do
Thanks "edey", but the above line will not compile.
Thanks "edey", but the above line will not compile.
ASKER
>> Well if you have D5
I am using Delphi 3
I am using Delphi 3
>Thanks "scrapdog", but your sample does not iterate through subfolders.
If you want it to recurse into subfolders, hang on a few minutes. I'll give you some code.
If you want it to recurse into subfolders, hang on a few minutes. I'll give you some code.
Well, maybe not. =)
Here is the code anyway:
procedure TForm1.Recurse(BasePath :TFilename; Criteria :TFilename; ListBox :TListBox);
var
SearchRec :TSearchRec;
Directories :TStringList;
i :integer;
procedure AddDirectory(Name :string);
begin
if (Name <> '.') and (Name <> '..') then Directories.Add(Name);
end;
procedure AddFile(const SearchRec :TSearchRec);
begin
if (SearchRec.Attr and faDirectory) = 0 then
ListBox.Items.Add(BasePath + SearchRec.Name);
end;
begin
if BasePath[Length(BasePath)] <> '\' then BasePath := BasePath + '\';
//get subdirectories
Directories := TStringList.Create;
if (FindFirst(BasePath + '*.*', faDirectory, SearchRec) = 0) then begin
AddDirectory(SearchRec.Nam e);
while(FindNext(SearchRec) = 0) do
AddDirectory(SearchRec.Nam e);
FindClose(SearchRec);
end;
if (FindFirst(BasePath + Criteria, faAnyFile, SearchRec) = 0) then begin
AddFile(SearchRec);
while(FindNext(SearchRec) = 0) do
AddFile(SearchRec);
FindClose(SearchRec);
for i := 0 to Directories.Count - 1 do
Recurse(BasePath + Directories[i], Criteria, ListBox);
Directories.Free;
end;
end;
procedure TForm1.Recurse(BasePath :TFilename; Criteria :TFilename; ListBox :TListBox);
var
SearchRec :TSearchRec;
Directories :TStringList;
i :integer;
procedure AddDirectory(Name :string);
begin
if (Name <> '.') and (Name <> '..') then Directories.Add(Name);
end;
procedure AddFile(const SearchRec :TSearchRec);
begin
if (SearchRec.Attr and faDirectory) = 0 then
ListBox.Items.Add(BasePath
end;
begin
if BasePath[Length(BasePath)]
//get subdirectories
Directories := TStringList.Create;
if (FindFirst(BasePath + '*.*', faDirectory, SearchRec) = 0) then begin
AddDirectory(SearchRec.Nam
while(FindNext(SearchRec) = 0) do
AddDirectory(SearchRec.Nam
FindClose(SearchRec);
end;
if (FindFirst(BasePath + Criteria, faAnyFile, SearchRec) = 0) then begin
AddFile(SearchRec);
while(FindNext(SearchRec) = 0) do
AddFile(SearchRec);
FindClose(SearchRec);
for i := 0 to Directories.Count - 1 do
Recurse(BasePath + Directories[i], Criteria, ListBox);
Directories.Free;
end;
end;
function search(base,mask : string);
var
sr : TSearchRec;
result : integer;
begin
result := findFirst(base+mask,faAnyF
while sr = 0 do
begin
if (sr.attr and faDirectory > 0)and(sr.name <> '.')and(sr.name <> '..') then
search(base+sr.name+'\',ma
else if sr.attr and faDirectory <= 0 then
form1.listBox1.items.add(b
result := findNext(sr);
end;
findClose(sr);
end;
ex.: search('c:\','*.pas') would find _all_ .pas files on drive c:. Base needs to end with a '\' & mask is any file mask.
Please note that this is completely untested, written "on the fly".
GL
Mike