Как создать расширение оболочки Property store

Расширение Property store позволяет в Windows XP определить значения, выводимые в колонках Проводника или добавить новые колонки, а в Windows Vista и более поздних системах обеспечить механизм извлечения свойств файла.

В библиотеке Shell Ace обработчик Icon реализует следующие интерфейсы:

После создания проекта расширения необходимо добавить в проект модуль с обработчиком Property store. Для этого выберите соответствующую иконку на вкладке Shell extension:

Создание обработчика Property store

Появится окно с предложением ввести имя класса и выбрать перекрываемые методы:

Методы обработчика Property store

После нажатия на кнопку OK в проект будет добавлен модуль с каркасом обработчика. При включении опции Create sample помимо каркаса обработчика будут создан пример готового расширения оболочки, который можно использовать для изучения библиотеки. Рекомендуется перекрывать метод CreateDataObjectFromStream или CreateDataObjectFromIStream, поскольку это даст возможность Проводнику передавать в расширение не только реальные объекты файловой системы, но и виртуальные объекты, например файл из zip архива.

В обработчике можно перекрывать следующие виртуальные процедуры и функции:

procedure Initialize;

Процедура инициализации обработчика, вызывается один раз при создании экземпляра обработчика.

procedure Clear;

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

class function GetClassID: TCLSID;

Функция должна возвращать уникальный идентификатор обработчика. Библиотека Shell Ace изначально генерирует уникальный идентификатор при генерации шаблона обработчика, поэтому менять его нет необходимости.

class function GetDescription: UnicodeString;

Функция должна возвращать описание обработчика.

procedure FillProgIDList(AList: TStrings);

В процедуре должно происходить заполнение списка AList ключами реестра, в которые будет прописан обработчик при регистрации расширения. Допускается добавление только расширений файлов! Регистрация части расширения, ответственной за отображение значения колонок и добавление новых колонок в Проводнике, производится в раздел реестра HKEY_CLASSES_ROOT\Folder\ShellEx\ColumnHandlers. А регистрация части расширения, ответственной за механизм извлечения и сохранения свойств файла, производится в раздел реестра HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers.

function CreateDataObjectFromStream(AStream: TStream; AOpenMode: DWORD): TObject;

Функция должна на основе потока AStream создать объект, из которого в дальнейшем будут извлекаться значения свойств файла. Функция вызывается в реализации метода GetItemData интерфейса IColumnProvider и в реализации методов GetValue и SetValue интерфейса IPropertyStore. Если переданный поток не возможно обработать, то нужно вернуть значение nil. Когда объект будет не нужен, то библиотека Shell Ace автоматически удалит его.

Параметр OpenMode определяет режим работы с потоком. Он может быть равен следующим величинам:

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

function CreateDataObjectFromIStream(AStream: IStream; AOpenMode: DWORD): TObject;

Метод аналогичен методу CreateDataObjectFromStream за исключением того, что вместо потока передается интерфейс IStream. Для создания потока для чтения данных из файла можно воспользоваться следующей функцией:

function CreateStream(AStream: IStream): TStream;

После использования полученного потока его нужно удалить.

Перекрытие данного метода может быть полезно в ситуациях, когда нет возможности извлечь все свойства сразу. Ссылку на интерфейс можно сохранять, например, в специальной переменной класса создаваемого объекта. Нужно не забывать освобождать интерфейс в методе Destroy класса создаваемого объекта.

function CreateDataObjectFromFileName(const AFileName: UnicodeString; AOpenMode: DWORD): TObject;

Метод аналогичен методу CreateDataObjectFromStream за исключением того, что вместо потока передается имя файла. Для создания потока для чтения данных из файла можно воспользоваться следующей функцией:

function CreateStream(const AFileName: UnicodeString; AOpenMode: DWORD = DefaultOpenMode): TStream;

После использования полученного потока его нужно удалить.

function CreateDataObjectFromFolderName(const AFolderName: UnicodeString): TObject;

Метод аналогичен методу CreateDataObjectFromFileName за исключением того, что вместо имени файла передается имя каталога. Функция вызывается в реализации метода GetItemData интерфейса IColumnProvider при передаче в параметрах имени каталога.

function GetPropertyCount: Integer;

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

function GetPropertyKey(AIndex: Integer): TPropertyKey;

Функция должна вернуть идентификатор свойства с индексом AIndex. Метод вызывается в реализации метода GetColumnInfo интерфейса IColumnProvider и в реализации метода GetAt интерфейса IPropertyStore. Идентификатор состоит из GUID и числового индекса. Рекомендуется использовать идентификаторы. Например, свойство "Размеры изображения" определяется комбинацией из GUID, равного FMTID_ImageSummaryInformation, и индекса, равного PIDISI_DIMENSIONS.

procedure GetPropertyInfo(AIndex: Integer; var AInfo: TdecPropertyInfo);

Функция должна заполнить структуру AInfo, определяющую тип свойства. Метод вызывается в реализации метода GetColumnInfo интерфейса IColumnProvider. Тип TdecPropertyInfo определен следующим образом:

TdecPropertyType = (ctString, ctInteger, ctDateTime);
TdecPropertyFlag = (cfOnByDefault, cfSlow, cfExtended, cfSecondaryUI, cfHidden, cfPreferVarCompare, cfPreferFormatCompare, cfNoSortByFolderness, cfViewOnly, cfBatchRead, cfNoGroupBy, cfFixedWidth, cfNoDPIScale, cfFixedRatio);
TdecPropertyFlags = set of TdecPropertyFlag;
TdecPropertyInfo = record
  VarType: TVarType;
  Alignment: TAlignment;
  Type_: TdecPropertyType;
  Flags: TdecPropertyFlags;
  Chars: UINT;
end;

function GetPropertyName(AIndex: Integer): UnicodeString;

Функция должна вернуть название свойства с индексом AIndex. Метод вызывается в реализации метода GetColumnInfo интерфейса IColumnProvider. Функция вызывается только если отсутствует системное название свойства.

function GetPropertyValue(AIndex: Integer; AObject: TObject): OleVariant;

function IsPropertyWritable(AIndex: Integer): Boolean;

procedure SetPropertyValue(AIndex: Integer; AObject: TObject; AValue: OleVariant);

procedure CommitToStream(AStream: TStream; AOpenMode: DWORD; AObject: TObject);

procedure CommitToIStream(AStream: IStream; AOpenMode: DWORD; AObject: TObject);

procedure CommitToFileName(const AFileName: UnicodeString; AOpenMode: DWORD; AObject: TObject);

Обязательными для реализации в обработчике Property store являются следующие методы:

  • GetClassID
  • FillProgIDList
  • GetPropertyCount
  • GetPropertyKey
  • GetPropertyValue
  • CreateDataObjectFromStream, CreateDataObjectFromIStream, CreateDataObjectFromFileName или CreateDataObjectFromFolderName

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