ディレクトリを再帰的に処理するには、FindFirstFile, FindNextFile, FindClose を利用します。
まあ、結局はファイル検索処理ですから。
function FindFirstFile(lpFileName: PChar; var lpFindFileData: TWin32FindData): THandle;
function FindNextFile(hFindFile: THandle; var lpFindFileData: TWin32FindData): BOOL;
function FindClose(hFindFile: THandle): BOOL;
再帰処理をするので、当然手続きを再帰的に使用します。
例えば、指定したディレクトリ下のファイルリストを作るなら、以下のような感じになります。
procedure FileListCreator(TopDir: TFileName);
var
Handle: THandle;
Data: TWin32FindData;
begin
Handle := Windows.FindFirstFile(PChar(TopDir + '\*.*'), Data);
if Handle = INVALID_HANDLE_VALUE then Exit;
if not ((StrPas(Data.cFileName) = '.') or (StrPas(Data.cFileName) = '..')) then
begin
FileList.Add(TopDir + '\' + StrPas(Data.cFileName));
if (Data.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
FileListCreator(TopDir + '\' + StrPas(Data.cFileName));
end;
while Windows.FindNextFile(Handle, Data) = True do
begin
if not ((StrPas(Data.cFileName) = '.') or (StrPas(Data.cFileName) = '..')) then
begin
FileList.Add(TopDir + '\' + StrPas(Data.cFileName));
if (Data.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
FileListCreator(TopDir + '\' + StrPas(Data.cFileName));
end;
end;
Windows.FindClose(Handle);
end;
Win32API の呼び出しに、Windows. がついているのは、FindClose が SysUtils.FindClose と衝突していたからです。
FindFirstFile と FindNextFile に関しては付ける必要はありません。
FindFirstFile, FindNextFile, FindClose に対応して、SysUtils にそれぞれ FindFirst, FindNext, FindClose があるようです。
こっちを使うのも悪くはないでしょう。
でも、Win32 API tips と一応銘打っているので、ここではこれ以上触れません
StrPas は Char 配列の文字列を、Pascal の文字列に変換する関数です。
多分、型変換でも問題ないと思います。
'.', '..'
に関しては、DOS 時代から PC を使ってる人なら分かるんですが、'.'
はディレクトリ自身を、'..'
は一つ上のディレクトリを意味します。
これらも処理してしまうと、当然ながら永久ループにご案内です(笑)
FileList は、どこかで宣言されている TStrings と仮定しています。
後は、FindFirstFile, FindNextFile, FindClose
を Win32API Help で引けばなんとかなるでしょう。