Листинг 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, можно использовать и при операциях, отличных от простого поиска: например, при копировании или удалении дерева каталогов. Для этого достаточно выполнять нужные операции над каждым найденным объектом.
Построение дерева каталогов
Рассмотрим довольно интересный пример, основанный на использовании функции поиска SearchlnFolder, – построение дерева каталогов для определенного диска (рис. 4.7).
Рис. 4.7. Дерево каталогов
Для простоты (и чтобы не отвлекать внимания от построения дерева) диск задается в программе жестко. При необходимости это можно легко исправить (как определять диски, вы уже знаете).
Рассмотрим работу приложения по порядку. Элемент управления TreeView на форме имеет имя tree. Содержимое списка изображений (ImageList), используемого деревом, приведено на рис. 4.8.
Первый элемент дерева (соответствует диску) образуется при создании формы (листинг 4.27).
Листинг 4.27.
Создание первого элемента дерева – диска
procedure TForm3.FormCreate(Sender: TObject);
begin
//Корневой элемент дерева (диск)
root := tree.Items.Add(tree.Items.GetFirstNode, \'C:\');
root.ImageIndex := 0;
root.SelectedIndex := 0;
SetExpanded(root, False);
end;
Здесь и далее в примере root позволяет быстро получать доступ к корневому элементу дерева. Используемая в листинге 4.27 процедура применяется для установки состояния элементов дерева (листинг 4.28).