Чтение онлайн

на главную - закладки

Жанры

Шрифт:

Поиск по всему дереву каталогов

В листинге 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, можно использовать и при операциях, отличных от простого поиска: например, при копировании или удалении дерева каталогов. Для этого достаточно выполнять нужные операции над каждым найденным объектом.

Построение дерева каталогов

Рассмотрим довольно интересный пример, основанный на использовании функции поиска SearchlnFolder, – построение дерева каталогов для определенного диска (рис. 4.7).

Рис. 4.7. Дерево каталогов

Для простоты (и чтобы не отвлекать внимания от построения дерева) диск задается в программе жестко. При необходимости это можно легко исправить (как определять диски, вы уже знаете).

Рассмотрим работу приложения по порядку. Элемент управления TreeView на форме имеет имя tree. Содержимое списка изображений (ImageList), используемого деревом, приведено на рис. 4.8.

Рис. 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).

...

Листинг 4.28.

Установка состояния элемента дерева

procedure TForm3.SetExpanded(Node: TTreeNode; isExpanded: Boolean);

begin

if isExpanded then

begin

//Подготавливаем элемент к загрузке содержимого каталога

Node.Data := Pointer(1);

Node.DeleteChildren;

end

else

begin

//Содержимое каталога не прочитано (или его следует обновить)

Node.Data := Pointer(0);

Node.Collapse(False);

Node.DeleteChildren;

tree.Items.AddChild(Node, \'\'); //Фиктивный элемент(чтобы

//отображался "+", позволяющий

//развернуть элемент)

end;

end;

Если после создания элементов дерева процедура SetExpanded вызывается с параметром isExpanded, равным False (как в листинге 4.27), то для переданного в процедуру элемента дерева создается фиктивный дочерний элемент. Это делается для того, чтобы не зачитывать содержимое каждого не развернутого еще элемента дерева (для папок с большим количество файлов программа будет сильно «тормозить»). А так у каждого еще не развернутого элемента отображается символ +, позволяющий развернуть его в нужный момент. При этом не нужно забывать удалять созданный фиктивный элемент дерева (что и делает SetExpanded с параметром isExpanded, равным True).

Каждый не развернутый еще элемент дерева помечается значением поля Node. Data, равным 0. Каждый элемент, содержимое которого уже прочитано с диска, помечается значением поля Node. Data, равным 1. Для проверки, было ли прочитано содержимое каталога, соответствующего элементу дерева, используется простая функция IsExpanded (листинг 4.29).

...

Листинг 4.29.

Проверка, загружено ли содержимое каталога

function TForm3.IsExpanded(Node: TTreeNode): Boolean;

begin

IsExpanded := Integer(Node.Data) = 1;

end;

Загрузка содержимого каталога и одновременное формирование дочерних элементов в дереве происходят при разворачивании элемента дерева (листинг 4.30).

...

Листинг 4.30.

Загрузка содержимого каталога

procedure TForm3.treeExpanding(Sender: TObject; Node: TTreeNode;

var AllowExpansion: Boolean);

var

strFolder: String;

subfolders: TStrings;

i: Integer;

item: TTreeNode;

begin

if not IsExpanded(Node) then

//Содержимое каталога нужно зачитать

SetExpanded(Node, True)

else

begin

//Список подкаталогов для выделенного каталога

//был составлен ранее

AllowExpansion := True;

Exit;

end;

//Составление списка подкаталогов

strFolder := NodeToFolderPath( Node );

subfolders := TStringList.Create;

if SearchInFolder(strFolder, \'*\', FILE_ATTRIBUTE_DIRECTORY,

subfolders)

then begin

//Добавим в дерево элементы, соответствующие подкаталогам

for i := 0 to subfolders.Count – 1 do

begin

item := tree.Items.AddChild(Node, subfolders[i]);

item.ImageIndex := 1;

item.SelectedIndex := 2;

SetExpanded(item, False); //Содержимое подкаталога еще

//не прочитано

end;

AllowExpansion := True;

end

else

//В каталоге нет подкаталогов

AllowExpansion := False;

subfolders.Free;

end;

В листинге 4.30 для определения пути каталога, заданного элементом дерева, используется функция NodeToFolderPath. Реализуется она совсем несложно (листинг 4.31).

...

Листинг 4.31.

Определение полного пути элемента дерева

function TForm3.NodeToFolderPath(Node: TTreeNode): String;

var

path: String;

item: TTreeNode;

begin

item := Node;

while item <> nil do

begin

if path <> \'\' then

path := item.Text + \'\\' + path

else

path := item.Text;

item := item.Parent;

end;

NodeToFolderPath := path;

end;

Поделиться:
Популярные книги

Убивать чтобы жить 6

Бор Жорж
6. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 6

Император Пограничья 10

Астахов Евгений Евгеньевич
10. Император Пограничья
Фантастика:
городское фэнтези
аниме
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 10

Надуй щеки! Том 6

Вишневский Сергей Викторович
6. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки! Том 6

Петля, Кадетский Корпус. Книга четвертая

Алексеев Евгений Артемович
4. Петля
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Петля, Кадетский Корпус. Книга четвертая

Офицер

Земляной Андрей Борисович
1. Офицер
Фантастика:
боевая фантастика
7.21
рейтинг книги
Офицер

#НенавистьЛюбовь

Джейн Анна
Любовные романы:
современные любовные романы
6.33
рейтинг книги
#НенавистьЛюбовь

Антимаг его величества

Петров Максим Николаевич
1. Модификант
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Антимаг его величества

Я все еще не князь. Книга XV

Дрейк Сириус
15. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я все еще не князь. Книга XV

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Мастер 11

Чащин Валерий
11. Мастер
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер 11

Чертова дюжина

Юллем Евгений
2. Псевдоним "Испанец" - 2
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Чертова дюжина

Мы – Гордые часть 8

Машуков Тимур
8. Стальные яйца
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мы – Гордые часть 8

Жена неверного маршала, или Пиццерия попаданки

Удалова Юлия
Любовные романы:
любовно-фантастические романы
4.25
рейтинг книги
Жена неверного маршала, или Пиццерия попаданки

Неучтенный элемент. Том 1

NikL
1. Антимаг. Вне системы
Фантастика:
городское фэнтези
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 1