Два месяца назад я научил тебя работать с дисками. Теперь пора заняться файловой системой. Основное, что мы сегодня изучим - организация поиска файлов и получение некоторой информации о них. Для этого есть два способа: использование функций WinAPI и встроенного в окна COM объекта. Сегодня нас интересует первый из них.
Исходники сегодняшнего примера, как всегда доступны в конце статьи. Можешь их скачать и проверить программу в работе, а на все возникающие вопросы ты получишь ответы в этой статье.
Рис 1. Пример формы
На рисунке 1, как всегда ты видишь пример рабочей проги, которая будет сегодня создана. Рассмотри рисунок. Если ты это сделал хорошо, то поймёшь, что для работы нам понадобиться один TListView, одна кнопка TButton, одна строка ввода TEdit и один TLabel для отображения текста везде строки ввода. Если ты любишь создавать примеры сам, а не использовать мои исходники, то расположи эти компоненты, как оказано на рисунке. Для работы примера нужен модуль shellapi , добавь его в раздел uses.
При рассмотрении примеров, обращай внимание на комментарии, они помогут тебе разобраться с происходящим в проге. А я буду расписывать только наиболее интересные моменты. Как всегда, начнём писать прогу с процедуры FormCreate. Вот как она выглядит:
procedure TForm1.FormCreate(Sender: TObject);
var
SysImageList: uint;
SFI: TSHFileInfo;
begin
//Создаю списки маленьких и больших иконок.
ListView1.Largeimages:=TImageList.Create(self);
ListView1.Smallimages:=TImageList.Create(self);
//Запрашиваю большие иконки
SysImageList := SHGetFileInfo('', 0, SFI,
SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_LARGEICON);
if SysImageList <> 0 then
begin
//Присваиваю системные иконки в ListView1
ListView1.Largeimages.Handle := SysImageList;
ListView1.Largeimages.ShareImages := TRUE;
end;
//Запрашиваю маленькие иконки
SysImageList := SHGetFileInfo('', 0, SFI, SizeOf(TSHFileInfo),
SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
if SysImageList <> 0 then
begin
ListView1.Smallimages.Handle := SysImageList;
ListView1.Smallimages.ShareImages := TRUE;
end;
end;
Функция SHGetFileInfo возвращает информацию о файле, директории или диске. Первый параметр - путь к файлу. Второй - атрибуты. Третий - указатель на ТSHFILEINFO. Четвертый - размер ТSHFILEINFO. Последний - флаги, указывающие на тип информации запрашиваемый у системы.
Теперь о том, как выглядит функция в моём примере. Первые два параметра пустые, это означает, что нам нужны глобальные данные. Если ты укажешь существующий файл, то ты получишь информацию по нему. В качестве флагов я указываю SHGFI_SYSICONINDEX и SHGFI_LARGEICON. SHGFI_SYSICONINDEX означает, что я запрашиваю указатель на системный список иконок (ImageList). Второй флаг говорит, что мне нужны большие иконки. При втором вызове этой функции я запрашиваю маленькие иконки (SHGFI_SMALLICON). Функция возвращает мне указатель на соответствующий системе SysImageList, который я в последствии присваиваю в ListView1.Largeimages.Handle.
Системный список иконок (ImageList) содержит все иконки, установленные в системе и ассоциированные с разными типами файлов. Эти иконки ты можешь видеть в Windows Explorer у вайлов doc, txt, ini, zip и др.
Теперь о процедуре FormShow. В ней я вызываю другую процедуру AddFile, которая считывает все файлы из текущей директории.
procedure TForm1.FormShow(Sender: TObject);
begin
AddFile(Edit1.Text+'*.*',faAnyFile)
end;
Процедуру AddFile я не буду приводить, потому что она слишком большая. Я лишь расскажу как она действует.
Внутри процедуры запускается поиск файлов в текущей директории.
//Запускаю поиск
hFindFile := FindFirst(Маска поиска, Аттрибуты , Информация);
//Проверяю корректность найденного файла
if hFindFile <> INVALID_HANDLE_VALUE then
//Если корректно, то запускаеться цикл repeat - until.
repeat
//Здесь вписаны операторы, которые нужно выпонять.
until (FindNext(SearchRec) <> 0);
FindClose(SearchRec);
FindFirst - открывает поиск. В качестве первого параметра выступает маска поиска. Если ты укажешь конкретный файл, то система найдёт его. Но это не серьёзно, лучше искать более серьёзные вещи. Например, ты можешь запустить поиск всех файлов в корне диска С. Для этого первый параметр должен быть 'C:\*.*'. Для поиска только файлов ЕХЕ, в папке Fold ты должен указать 'C:\Fold\*.exe'.
Второй параметр - атрибуты включаемых в поиск файлов. Я использую faAnyFile, чтобы искать любые файлы. Тебе доступны
faReadOnly - искать файлы с атрибутом ReadOnly.
faHidden - искать скрытые файлы.
faSysFile - искать системные файлы.
faArchive - искать архивные файлы.
faDirectory - искать директории.
Паследний параметр - это структура в которой нам вернёться информация о поиске, а именно имя найденного файла, размер, время создания и т.д. После вызова этой процедуры, я проверяю на корректность найденного файла. Если всё в норме, то запускаеться цикл Repeat - Until. Этот цикл выполняет операторы расположенные между repeat и until, пока условие расположенное после слова until являеться верным. Как только условие нарушается, цикл прерывается. Этот цикл похож на while, но с одним отличием. Если в цикле while условие заведомо не верно, то операторы внутри цикла не выпоняться. А в Repeat-Until выполнятся, потому что сначала происходит выполнение операторов, а лишь затем проверка Until. Рассмотрим пример:
index:=1;
while index=0 do
Param:=0;
В этом примере оператор Param:=0; не будет выполнен, потому что index=1 и условие заведомо не верно.
index:=1;
repeat
Param:=0;
until index=0;
В этом примере Param:=0 выполнится, Потому что сначала выполняется этот оператор, а лишь потом проверка на равенство index нулю.
Хочу предупредить, что функция поиска, может возвращать в качестве найденного имени в структуре SearchRec (параметр Name) точку или две точки. Если ты посмотришь на директорию, то таких файлов не будет. Откуда берутся эти имена? Имя файла в виде точки указывает на текущую директорию, а имя файла из двух точек указывает на директорию верхнего уровня. Если я встречаю такие имена, то я их просто отбрасываю.
Принцип ясен? А с самой работой разберёшься по исходнику, ты уже не маленький. До встречи!!