// FindFiles - Klasse zum Durchsuchen von Ordnern
// Michael Puff [[url]http://www.michael-puff.de][/url], himitsu, omata
unit MpuFindFilesCls;
interface
uses
Windows;
type
TOnFindFile =
procedure(Filename:
string;
const Info: TWin32FindData;
var Cancel: Boolean)
of object;
TOnFindDirectory =
procedure(Directory:
string;
const Info: TWin32FindData;
var Cancel: Boolean;
var IgnoreDirectory: Boolean)
of object;
TOnDirectoryUp =
procedure(FromDirectory, ToDirectory:
string;
var Cancel: Boolean)
of object;
TFindFiles =
class(TObject)
private
FSubfolders: Boolean;
FMask:
string;
FCancel: Boolean;
FOnFindFile: TOnFindFile;
FOnFindDirectory: TOnFindDirectory;
FOnDirectoryUp: TOnDirectoryUp;
function DirectoryExists(
const Directory:
string): Boolean;
procedure Search(RootFolder:
string);
public
constructor Create;
procedure Find(RootFolder:
string);
property SubFolders: Boolean
read FSubFolders
write FSubFolders;
property Mask:
string read FMask
write FMask;
property OnFindFile: TOnFindFile
read FOnFindFile
write FOnFindFile;
property OnFindDirectory: TOnFindDirectory
read FOnFindDirectory
write FOnFindDirectory;
property OnDirectoryUp: TOnDirectoryUp
read FOnDirectoryUp
write FOnDirectoryUp;
end;
type
Exception =
class(TObject)
private
FMsg:
string;
class function SysErrorMessage(ErrorCode: Integer):
string;
public
constructor Create(Msg:
string);
property Msg:
string read FMsg;
end;
implementation
{ TFindFiles }
constructor TFindFiles.Create;
begin
inherited;
FSubfolders := False;
FMask := '
*.*';
end;
procedure TFindFiles.Search(RootFolder:
string);
var
wfd: TWin32FindData;
hFile: THandle;
Ignore: Boolean;
begin
if (RootFolder <> '
')
and (RootFolder[Length(RootFolder)] <> '
\')
then
RootFolder := RootFolder + '
\';
if not FCancel
and FSubFolders
then
begin
hFile := FindFirstFile(PChar(RootFolder + '
*.*'), wfd);
if hFile <> INVALID_HANDLE_VALUE
then
try
repeat
if wfd.dwFileAttributes
and FILE_ATTRIBUTE_DIRECTORY <> 0
then
if (
string(wfd.cFileName) <> '
.')
and (
string(wfd.cFileName) <> '
..')
then
begin
Ignore := False;
if Assigned(FOnFindDirectory)
then
FOnFindDirectory(RootFolder + wfd.cFileName, wfd, FCancel, Ignore);
if not FCancel
and not Ignore
then
Find(RootFolder + wfd.cFileName + '
\');
if not FCancel
and Assigned(FOnDirectoryUp)
then
FOnDirectoryUp(RootFolder + wfd.cFileName, RootFolder, FCancel);
end;
until FCancel
or not FindNextFile(hFile, wfd);
finally
windows.FindClose(hFile);
end;
end;
if not FCancel
and Assigned(OnFindFile)
then
begin
hFile := FindFirstFile(PChar(RootFolder + FMask), wfd);
if hFile <> INVALID_HANDLE_VALUE
then
try
repeat
if wfd.dwFileAttributes
and FILE_ATTRIBUTE_DIRECTORY = 0
then
OnFindFile(RootFolder + wfd.cFileName, wfd, FCancel);
until FCancel
or not FindNextFile(hFile, wfd);
finally
Windows.FindClose(hFile);
end;
end;
end;
procedure TFindFiles.Find(RootFolder:
string);
begin
if not DirectoryExists(RootFolder)
then
begin
raise Exception.Create(
Exception.SysErrorMessage(GetLastError));
end;
FCancel := False;
Search(RootFolder);
end;
function TFindFiles.DirectoryExists(
const Directory:
string): Boolean;
var
Code: Integer;
begin
Code := GetFileAttributes(PChar(Directory));
Result := (Code <> -1)
and (FILE_ATTRIBUTE_DIRECTORY
and Code <> 0);
end;
{ Exception }
constructor Exception.Create(Msg:
string);
begin
FMsg := Msg;
end;
class function Exception.SysErrorMessage(ErrorCode: Integer):
string;
var
Len: Integer;
Buffer:
array[0..255]
of Char;
begin
Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
or
FORMAT_MESSAGE_ARGUMENT_ARRAY,
nil, ErrorCode, 0, Buffer,
SizeOf(Buffer),
nil);
while (Len > 0)
and (Buffer[Len - 1]
in [#0..#32, '
.'])
do
Dec(Len);
SetString(Result, Buffer, Len);
end;
end.