- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Delphi. Трюки и эффекты - Валерий Борисок
Шрифт:
Интервал:
Закладка:
Каждому из рассмотренных атрибутов соответствует бит в возвращаемом функцией GetFileAttributes значении. Вот отрывок программы, определяющей, является ли файл системным:
...var attrs: DWORD;
begin
attrs := GetFileAttribute(PAnsiChar('C:boot.ini'));
if (attrs and FILE_ATTRIBUTE_SYSTEM <> 0) then {файл системный};
Атрибуты устанавливаются при помощи API-функции SetFileAttributes. Она принимает два параметра: путь файла или папки (PChar) и битовую маску атрибутов. Возвращает 0 (False) в случае неудачи и ненулевое значение в противном случае.
Поскольку в функцию SetFileAttributes передается маска, хранящая сведения сразу обо всех атрибутах файла или папки, то изменять атрибуты нужно аккуратно (чтобы не удалить установленные ранее). Пример (отрывок программы) «включения» одного и одновременного «выключения» другого атрибута файла приведен в листинге 4.22 (проверка ошибок для простоты не производится).
...Листинг 4.22.
Изменение атрибутов файла
var attrs: DWORD;
begin
attrs := GetFileAttributes('C:text.txt');
attrs := attrs or FILE_ATTRIBUTE_HIDDEN; //Установка атрибута «скрытый»
attrs := attrs and not FILE_ATTRIBUTE_ARCHIVE; //Снятие атрибута «архивный»
SetFileAttributes('C:text.txt', attrs);
Поиск в указанной папке
Поиск в пределах одной папки представляет собой простой перебор всех элементов каталога с отбором тех, имена которых удовлетворяют маске и заданному набору атрибутов. В приведенном ниже примере (листинг4.23) используется API-функция FindFirstFile, которая начинает просмотр заданного каталога, автоматически отсеивая имена файлов и папок, не удовлетворяющи х маске. Функция возвращает дескриптор (THandle), используемый для идентификации начатого просмотра папки при продолжении поиска (в функции FindNextFile).
После окончания просмотра папки вызывается функция FindClose, завершающая просмотр папки. Очень напоминает работу с обычным файлом (открытие, просмотр, закрытие), не так ли?
...Листинг 4.23.
Поиск в заданной папке
function SearchInFolder(folder, mask: String; flags: DWORD;
names: TStrings; addpath: Boolean = False): Boolean;
var
hSearch: THandle;
FindData: WIN32_FIND_DATA;
strSearchPath: String;
bRes: Boolean; //Если равен True, то нашли хотя бы один
//файл или каталог
begin
strSearchPath := folder + '\' + mask;
bRes := False;
//Начинаем поиск
hSearch := FindFirstFile(PAnsiChar(strSearchPath), FindData);
if (hSearch <> INVALID_HANDLE_VALUE) then
begin
//Ищем все похожие элементы (информация о первом элементе
//уже записана в FindData функцией FindFirstFile)
repeat
if (String(FindData.cFileName) <> '..') and
(String(FindData.cFileName) <> '.') then
//Пропускаем . и ..
begin
if MatchAttrs(flags, FindData.dwFileAttributes) then
begin
//Нашли подходящий объект
if addpath then
names.Add(folder + '\' + FindData.cFileName)
else
names.Add(FindData.cFileName);
bRes := True;
end;
end;
until FindNextFile(hSearch, FindData) = False;
//Заканчиваем поиск
FindClose(hSearch);
end;
SearchInFolder := bRes;
end;
Результатом работы функции SearchlnFolder является заполнение списка names именами или, если значение параметра addpath равно True, полными путями найденных файлов и каталогов. Значение параметра flags (битовая маска атрибутов) формируется так же, как для функции SetFileAttributes. Только одновременно можно установить любые интересующие программиста атрибуты. При нахождении хотя бы одного файла или каталога SearchlnFolder возвращает значение True.
В функции поиска проверка соответствия атрибутов найденных файлов и каталогов производится при помощи дополнительной функции 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, можно использовать и при операциях, отличных от простого поиска: например, при копировании или удалении дерева каталогов. Для этого достаточно выполнять нужные операции над каждым найденным объектом.
Построение дерева каталогов
Рассмотрим довольно интересный пример, основанный на использовании функции поиска 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
//Содержимое каталога не прочитано (или его следует обновить)

