Класс TdecShellFileList

Расширения оболочки, такие как Context menu или Property Sheet, в общем случае работают не с одним файлом, а с несколькими. В ОС Windows существуют несколько форматов представления списка файлов, основанных на интерфейсе IDataObject, которые и используются при передаче списка в расширение оболочки. В каждой новой версии ОС Windows количество форматов растет, новые форматы позволяют производить более быструю навигацию, позволяют передавать "виртуальные" файлы, например, объекты Корзины или файлы из состава zip-архива. В целях обратной совместимости даже в Windows 8 в дополнение к новым форматам все также используются и старые. Но расширением оболочки также может пользоваться не только сама ОС Windows, но и любая другая программа, и нет гарантий, что эта программа будет также использовать старые форматы. Поэтому идеальное расширение должно поддерживать все форматы представления списка файлов, как старые, так и новые. Именно это и реализовано в библиотеке Shell Ace через класс TdecShellFileList.

В библиотека Shell Ace вся работа с форматами происходит незаметно для разработчика. Разработчик получает для работы объект класса TdecShellFileList, в недрах которого скрыта вся работа по обработке всех форматов списков файлов.

В классе TdecShellFileList поддерживаются следующие форматы списков файлов:

Класс TdecShellFileList предоставляет унифицированный интерфейс получения списка файлов, не зависящий от формата. Интерфейс представляет собой следующие методы класса TdecShellFileList:

function FindFirst(var ASearchRec: TdecSearchRec): TdecSearchHandle;

Функция ищет первый файл в списке. В случае удачи функция вернет идентификатор перечисления, отличный от нуля, а параметр ASearchRec будет заполнен информацией о файле. Если файл не найден, то возвращаемый идентификатор будет равен нулю, а значение параметра ASearchRec будет не определено.

Тип TdecSearchRec представляет собой запись:

TdecSearchRec = record
  FileName: UnicodeString;
  Attr: DWORD;
  CreationTime: TFileTime;
  LastAccessTime: TFileTime;
  LastWriteTime: TFileTime;
  FileSize: Int64;
end;

В поле FileName записано имя файла, включая путь (при его наличии). В поле Attr записаны атрибуты файла. В поля CreationTime, LastAccessTime и LastWriteTime записаны даты создания, последнего доступа и модификации файла. В поле FileSize записан размер файла.

function FindNext(ASearchHandle: TdecSearchHandle; var ASearchRec: TdecSearchRec): Boolean;

Функция ищет следующий файл в списке. В параметре ASearchHandle передается полученный в методе FindFirst идентификатор. В случае, если следующий файл в списке найден успешно, то функция вернет True, а параметр ASearchRec будет заполнен информацией о файле. В случае, если файлов в списке более нет, то функция вернет False, а значение параметра ASearchRec будет не определено.

procedure FindClose(ASearchHandle: TdecSearchHandle);

Функция освобождает все ресурсы, связанные с перечислением файлов.

function CreateFileStream(ASearchHandle: TdecSearchHandle; const ASearchRec: TdecSearchRec; AOpenMode: DWORD = DefaultOpenMode; ASeekSupport: Boolean = True): TStream;

Функция предназначена для создания потока с данными файла, описанного в параметре ASearchRec. В параметре ASearchHandle передается полученный в методе FindFirst идентификатор. В параметре ASearchRec передается запись, полученная в методе FindFirst или FindNext. Параметр AOpenMode определяет режим открытия файла. Доступны следующие значения:

  • STGM_READ – файл открывается только для чтения, константа DefaultOpenMode имеет именно это значение.
  • STGM_READWRITE – файл открывается как для чтения, так и для записи, поддерживается не всеми форматами списков файлов.

При передаче списка файлов в формате CF_FILEDESCRIPTOR ОС Windows создает потоки данных, которые не поддерживают функцию Seek. При использовании такого потока при вызове данного метода возникнет исключение. Для предотвращения такой ситуации можно определить параметр ASeekSupport в значение True. При этом библиотека Shell Ace при необходимости создаст временный поток, в который будет скопировано все содержимое оригинального потока, и этот временный поток будет поддерживать функцию Seek. Нужно учитывать, что это влечет за собой дополнительный расход памяти, поэтому если функциональность метода Seek не требуется, то лучше установить параметр ASeekSupport в значение False.

function CreateFolderFileList(ASearchHandle: TdecSearchHandle; const ASearchRec: TdecSearchRec): TdecShellFileList;

Функция предназначена для создания нового объекта класса TdecShellFileList, который будет перечислять содержимое директории, описанной в параметре ASearchRec. В параметре ASearchHandle передается полученный в методе FindFirst идентификатор. В параметре ASearchRec передается запись, полученная в методе FindFirst или FindNext.

function CreateFileList: TStrings;

Функция создает объект класса TStrings, который будет содержать имена всех файлов и директорий списка. В списке могут быть как имена реальных файлов, так и виртуальных. В версиях Delphi вплоть до версии 2009, в которых тип string равен типу AnsiString, имена файлов в списке хранятся в формате UTF8. После работы со списком он должен быть удален. Для перевода имени файла из сроки, хранящейся в TStrings в UnicodeString можно воспользоваться функцией StringToUnicodeString. Эта функция в версиях Delphi вплоть до версии 2009 производит преобразование строки из UTF8 в UnicodeString, в более старших версиях просто возвращает переданное значение.

function IsSingleFile: Boolean;

Функция вернет True, если список состоит из одного файла.

function GetCount: Integer;

Функция вернет количество файлов и директорий в списке.

В общем случае работа со объектом класса TdecShellFileList происходит следующим образом:

procedure Work(AFileList: TdecShellFileList);
var SearchHandle: THandle;
    SearchRec: TdecSearchRec;
begin
  SearchHandle := AFileList.FindFirst(SearchRec);
  if SearchHandle <> 0 then
    try
      repeat
        // Process file or folder
      until not AFileList.FindNext(SearchHandle, SearchRec);
    finally
      AFileList.FindClose(SearchHandle);
    end;
end;

Содержимое списка в общем случае может быть совершенно разным. В списке могут быть файлы из разных директорий. В списке могут быть не только файлы, но и директории. В списке могут быть не только реальные файлы и директории, но и виртуальные. Это может быть, например, вложение из электронного письма или файл из zip-архива.

Определить, что в параметре SearchRec возвращена директория можно по наличию флага FILE_ATTRIBUTE_DIRECTORY в поле Attr, а определить, что объект является виртуальным можно по наличию флага FILE_ATTRIBUTE_VIRTUAL.

Смотрите также: