В функции поиска проверка соответствия атрибутов найденных файлов и каталогов производится при помощи дополнительной функции MatchAttrs. Код этой функции приведен в листинге 4.24.
...
Листинг 4.24.
Фильтр атрибутов
function MatchAttrs(flags, attrs: DWORD): Boolean;
begin
MatchAttrs := (flags and attrs) = flags;
end;
Может показаться, что проверка из одной строки – слишком слабый аргумент для создания отдельной функции. В рассматриваемом примере отдельная функция MatchAttrs выделена для того, чтобы сделать отсеивание файлов (и папок) по атрибутам более очевидным.
В листинге 4.24 приводится реализация нестрогого фильтра: он принимает файл или папку, если они имеют все установленные в flags атрибуты, независимо от наличия файла или папки дополнительных атрибутов. Так, если мы задали flags:= FILE_ATTRIBUTE_READONLY, то будут найдены как файлы, так и каталоги, а также скрытые, системные и прочие файлы, также имеющие атрибут FILE_ATTRIBUTE_READONLY. Для реализации строгого фильтра можно заменить выражение в функции MatchAttrs простым равенством: flags = attrs.
Возможный результат поиска с использованием функции SearchlnFolder приводится на рис. 4.5.
Рис. 4.5. Поиск в заданной папке
Пример вызова функции SearchlnFolder (для показанного на рис. 4.5 приложения) приведен в листинге 4.25.
...
Листинг 4.25.
Использование функции SearchlnFolder
//Запуск поиска файла в заданной папке
procedure TForm2.Button1Click(Sender: TObject);
var
flags: DWORD;
begin
//Формируем набор атрибутов (по установленным флажкам на форме)
flags := 0;
if (chkDirs.Checked) then flags := flags or FILE_ATTRIBUTE_DIRECTORY;
if (chkHidden.Checked) then flags := flags or FILE_ATTRIBUTE_HIDDEN;
if (chkSystem.Checked) then flags := flags or FILE_ATTRIBUTE_SYSTEM;
if (chkReadOnly.Checked) then flags := flags or FILE_ATTRIBUTE_READONLY;
if (chkArchive.Checked) then flags := flags or
FILE_ATTRIBUTE_ARCHIVE;
lblFound.Caption := \'Поиск…\
lstFiles.Clear;
Refresh;
//Поиск (файлы записываются прямо в список на форме)
if not SearchInFolder(txtFolder.Text, txtMask.Text, flags,
lstFiles.Items)
then
lblFound.Caption := \'Поиск не дал результатов\'
else
lblFound.Caption := \'Найдено объектов: \' +
IntToStr(lstFiles.Count);
end;
Поиск по всему дереву каталогов
В листинге 4.26 приводится одна из возможных реализаций рекурсивного поиска по дереву каталогов. Алгоритм поиска работает следующим образом.
1. Выполняется поиск в папке folder(все найденные файлы или папки добавляются в список names).
2. Функция SearchlnTree вызывается для каждого подкаталога BfoLder для продолжения поиска в поддереве, определяемом подкаталогом.
...
Листинг 4.26.
Поиск по дереву каталогов
function SearchInTree(folder, mask: String; flags: DWORD;
names: TStrings; addpath: Boolean = False): Boolean;
var
hSearch: THandle;
FindData: WIN32_FIND_DATA;
bRes: Boolean; //Если равен True, то нашли хотя бы один файл или каталог
begin
//Осуществляем поиск в текущей папке
bRes := SearchInFolder(folder, mask, flags, names, addpath);
//Продолжим поиск в каждом из подкаталогов
hSearch := FindFirstFile(PAnsiChar(folder + \'\*\'), FindData);
if (hSearch <> INVALID_HANDLE_VALUE) then
begin
repeat
if (String(FindData.cFileName) <> \'..\') and
(String(FindData.cFileName) <> \'.\') then
//Пропускаем . и ..
begin
if (FindData.dwFileAttributes and
FILE_ATTRIBUTE_DIRECTORY <> 0)
then
//Нашли подкаталог – выполним в нем поиск
if SearchInTree(folder + \'\\' + String(FindData.cFileName),
mask, flags, names, addpath)
then
bRes := True;
end;
until FindNextFile(hSearch, FindData) = False;
FindClose(hSearch);
end;
SearchInTree := bRes;
end;
В функции SearchlnTree не используется просмотр каталога folder вручную (при помощи API-функций) из соображений эффективности. Если захотите, можете реализовать поиск подкаталогов при помощи функции SearchlnFolder. Правда, при этом нужно будет завести дополнительный список (TStringList) для сохранения найденных в текущем каталоге подкаталогов. Элементы списка будут использоваться только один раз: для поиска в подкаталогах.
Возможный результат поиска с использованием функции SearchlnTree приводится на рис. 4.6.
Рис. 4.6. Поиск по дереву каталогов
С небольшими модификациями алгоритм рекурсивного обхода дерева каталогов, реализованный в листинге 4.25, можно использовать и при операциях, отличных от простого поиска: например, при копировании или удалении дерева каталогов. Для этого достаточно выполнять нужные операции над каждым найденным объектом.
Построение дерева каталогов
Читать дальше
Конец ознакомительного отрывка
Купить книгу