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

Расширение Icon позволяет динамически определять иконку файла.

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

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

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

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

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

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

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

procedure Initialize;

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

procedure Clear;

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

class function GetClassID: TCLSID;

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

class function GetDescription: UnicodeString;

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

procedure FillProgIDList(AList: TStrings);

В процедуре должно происходить заполнение списка AList ключами реестра, в которые будет прописан обработчик при регистрации расширения. Регистрация происходит в раздел реестра HKEY_CLASSES_ROOT. Например, если будет добавлен ключ .bmp, то расширение будет прописано в ветку HKEY_CLASSES_ROOT\.bmp\ShellEx\IconHandler и будет соответствовать всем файлам, имеющим расширение bmp, а если будет добавлен ключ SystemFileAssociations\Audio, то расширение будет прописано в ветку HKEY_CLASSES_ROOT\SystemFileAssociations\Audio\ShellEx\IconHandler и будет соответствовать всем файлам, расширения которых имеют PerceivedType Audio.

При добавлении ключа реестра нужно учитывать, что в Windows определен порядок приоритета обработчиков. И если в системе зарегистрирован обработчик с более высоким приоритетом, то ваш обработчик не будет вызываться.

Порядок приоритета типов объектов, в порядке уменьшения приоритета, может отличаться в различных версиях Windows:

Ключ реестраПримечание
HKCR\ProgIDЕсли для расширения файла определено значение Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.Расширение\UserChoice
HKCR\ProgIDЕсли для расширения файла определено значение ProgID
HKCR\.РасширениеРасширение файла
HKCR\SystemFileAssociations\.РасширениеСистемное расширение файла
HKCR\SystemFileAssociations\PerceivedTypeЕсли для расширения файла определено значение PerceivedType
HKCR\Kind.KindЕсли для расширения файла определено значение Kind
HKCR\UnknownФайл, не имеющий описанного в реестре расширения
HKCR\*Любой файл

В общем случае рекомендуется регистрировать расширение на ProgID расширения файла.

function CreateIconInfoFromStream(AStream: TStream; AOpenMode: DWORD; ADefault: Boolean; AFlags: TdecIconFlags; var AIconFileName: UnicodeString; var AIconIndex: Integer; var AOutFlags: TdecIconOutFlags; var AShield: TdecIconShield): Boolean;

Функция должна на основании потока с данными AStream сформировать информацию о иконке, вызывается в реализации метода GetIconLocation интерфейса IExtractIcon.

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

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

Параметр ADefault определяет, что оболочка запрашивает информацию о иконке по умолчанию, т.е. о иконке, которая будет отображаться во время извлечения полноценной иконки. Параметр равен True при передаче в метод GetIconLocation флага GIL_DEFAULTICON.

Для формирования информации о иконке можно дополнительно анализировать флаги AFlags. Тип TdecIconFlags определен следующим образом:

TdecIconFlag = (ifForShell, ifForShortCut, ifOpenIcon);
TdecIconFlags = set of TdecIconFlag;

Каждый из элементов множества соответствует одному из флагов, переданных в метод GetIconLocation интерфейса IExtractIcon.

ЗначениеWinAPI флагОписание
ifForShellGIL_FORSHELLThe icon is displayed in a Shell folder.
ifForShortCutGIL_FORSHORTCUTОболочка запрашивает информацию об иконке для объекта, который является ссылкой. Обработчик не должен добавлять оверлейную иконку на создаваемую обработчиком иконку, это будет сделано самим Проводником.
ifOpenIconGIL_OPENICONОболочка запрашивает информацию о иконке для объекта в состоянии "открыто" в ситуации, когда доступны состояния "открыто" и "закрыто". Если флаг не определен, то запрашивается информацию о иконке для объекта в состоянии "закрыто". Флаг используется для таких объектов, как папка.

Флаги GIL_ASYNC и GIL_CHECKSHIELD библиотека Shell Ace обрабатывает самостоятельно.

Параметры AIconFileName и AIconIndex будут переданы в дальнейшем в функцию CreateIconFromStream или CreateIconFromFileName.

Параметр AOutFlags позволяет передать в оболочку дополнительны параметры. Тип TdecIconOutFlags определен следующим образом:

TdecIconOutFlag = (iofSlow, iofDontCache, iofNotFileName, iofPerClass, iofPerInstance, iofSimulateDoc);
TdecIconOutFlags = set of TdecIconOutFlag;

Каждый из элементов множества, кроме iofSlow, соответствует одному из флагов, возвращаемых в оболочку методом GetIconLocation интерфейса IExtractIcon.

ЗначениеWinAPI флагОписание
iofSlowСоздание иконки занимает продолжительное время.
iofDontCacheGIL_DONTCACHEОболочка не должна кэшировать полученную иконку.
iofNotFileNameGIL_NOTFILENAMEПараметры AIconFileName и AIcon не является корректным именем файла и индексом иконки и не могут быть переданы в функции ExtractIcon или ExtractIconEx.
iofPerClassGIL_PERCLASSВсе объекты этого класса имеют одну и туже иконку. В общем случае обработчик Icon не использует этот флаг, поскольку он обозначает, что данный обработчик не будет использоваться для получения иконок других объектов данного класса.
iofPerInstanceGIL_PERINSTANCEКаждый объект этого класса имеет собственную иконку.
iofSimulateDocGIL_SIMULATEDOCОболочка должна создать иконку документа с использованием полученной иконки.

Флаги GIL_SHIELD и GIL_FORCENOSHIELD библиотека Shell Ace обрабатывает самостоятельно.

Параметр AShield позволяет определить необходимость отображения иконки UAC поверх полученной иконки.

Тип TdecIconShield определен следующим образом:

TdecIconShield = (isNoShield, isShield);

По умолчанию AShield имеет значение isNoShield.

function CreateIconInfoFromFile(const AFileName: UnicodeString; AOpenMode: DWORD; ADefault: Boolean; AFlags: TdecIconFlags; var AIconFileName: UnicodeString; var AIconIndex: Integer; var AOutFlags: TdecIconOutFlags; var AShield: TdecIconShield): Boolean;

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

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

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

function CreateIconFromStream(AStream: TStream; AOpenMode: DWORD; const AIconFileName: UnicodeString; AIconIndex: Integer; ASize: Integer): HICON;

Функция должна на основании потока с данными AStream создать иконку и вернуть ее идентификатор (handle), вызывается в реализации метода Extract интерфейса IExtractIcon.

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

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

Параметры AIconFileName и AIconIndex равны одноименным параметрам, ранее полученным в функциях CreateIconInfoFromStream или CreateIconInfoFromFileName.

Параметр ASize определяет ширину и высоту запрашиваемой иконки в пикселях. В нормальных условиях оболочка может запрашивать иконки с размерами 16x16, 32x32, 48x48 и 256x256. Если будет создана иконка с размерами, отличающимися от запрашиваемых, то библиотека Shell Ace самостоятельно преобразует ее к нужным размерам. Если в среде разработки установлен пакет Graphics32, то рекомендуется добавлять в список используемых модулей модуль decShellExtensionGraphics32. Это позволит библиотеке Shell Ace использовать более плавные процедуры сглаживания иконок при увеличении или уменьшении их размеров. Если библиотека обнаружит установленный пакет Graphics32, то модуль decShellExtensionGraphics32 будет автоматически добавлен в список используемых модулей при создании каркаса обработчика.

Если нужно, что бы оболочка самостоятельно извлекла иконку на основе параметров AIconFileName и AIconIndex, ранее полученных в функциях CreateIconInfoFromStream или CreateIconInfoFromFileName, вместо идентификатора иконки нужно вернуть ноль.

function CreateIconFromFile(const AFileName: UnicodeString; AOpenMode: DWORD; const AIconFileName: UnicodeString; AIconIndex: Integer; ASize: Integer): HICON;

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

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

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

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

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