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

Обработчик Drop target позволяет определить действие, которое будет происходить при операции перетаскивания объектов на файл. Объектом может выступать не только файл, но и, например, текст, перетаскиваемый из текстового редакотра, или изображение, перетаскиваемого из графического редакотра. Также данный обработчик используется Проводником для формирования контекстного меню файла.

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

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

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

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

Методы обработчика Drop target

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

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

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\DropHandler и будет соответствовать всем файлам, имеющим расширение bmp, а если будет добавлен ключ SystemFileAssociations\Audio, то расширение будет прописано в ветку HKEY_CLASSES_ROOT\SystemFileAssociations\Audio\ShellEx\DropHandler и будет соответствовать всем файлам, расширения которых имеют 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 CanDropDataObjectToFile(ASourceDataObject: IDataObject; const ADestFileName: UnicodeString; AOpenMode: DWORD; AAvailableEffects: TdecDropEffects; AShiftState: TShiftState): TdecDropEffect;

Функция должна вернуть тип действия, которое будет производиться при перетаскивании объектов, переданных в интерфейсе IDataObject, на файл с именем ADestFileName. Функция вызывается из реализации методов DragEnter и DragOver интерфейса IDropTarget.

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

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

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

Параметр AAvailableEffects определяет список доступных типов действий. Тип TdecDropEffects определен следующим образом:

TdecDropEffect = (deNone, deCopy, deMove, deLink);
TdecDropEffects = set of TdecDropEffect;

Каждое из значений соответствует определенному флагу, возвращаемому методами DragEnter и DragOver интерфейса IDropTarget.

ЗначениеWinAPI флагОписание
deNoneDROPEFFECT_NONEПосле операции перетаскивания не будет произведено никаких действий.
deCopyDROPEFFECT_COPYПосле операции перетаскивания будет произведена операция копирования перетаскиваемого объекта.
deMoveDROPEFFECT_MOVEПосле операции перетаскивания будет произведена операция перемещения перетаскиваемого объекта.
deLinkDROPEFFECT_LINKПосле операции перетаскивания будет произведена операция создания ссылки на перетаскиваемый объект.

Для определения типа действия можно дополнительно анализировать состояние клавиш Alt, Ctrl и Shift, которые передаются в параметре ShiftState. В Windows принято следующее соотношение между нажатыми клавишами и типом действия:

КлавишиОписание
Ctrl + ShiftСоздание ссылки на перетаскиваемый объект.
CtrlКопирование перетаскиваемого объекта.
Shift или клавиши Alt, Ctrl и Shift не нажатыПеремещение перетаскиваемого объекта.

Указанные соответствия являются просто рекомендациями, в реальных обработчиках в зависимости от решаемых задач можно использовать иные варианты обработки нажатия клавиш.

Через переданный интерфейс IDataObject можно получить перетаскиваемые объекты. Нужно учитывать, что через интерфейс IDataObject могут передаваться совершенно различные объекты. Например, при перетаскивании файлов из Проводника будет передан список реальных файлов, при перетаскивании файлов из zip-архива будет передан список виртуальных файлов, а при перетаскивании графического объекта из документа, открытого в программе Microsoft Word, будет передан (в том числе и) метафайл.

Для облегчения работы со списком переданных объектов можно воспользоваться функцией CreateShellFileList:

function CreateShellFileList(ADataObject: IDataObject): TdecShellFileList;

Описание работы с классом TdecShellFileList можно прочитать здесь. После работы с объектом он должен быть удален. Если в интерфейсе IDataObject имена файлов не найдены, то функция CreateShellFileList вернет nil.

Особенностью работы с объектом TdecShellFileList в процедуре CanDropDataObjectToFile является то, что в ряде случаев в интерфейсе IDataObject могут передаваться имена не существующих файлов, например, если осуществлять операцию перетаскивания объектов из программы-архиватора WinRar. Изначально программа WinRar передает в расширение список имен перетаскиваемых из архива файлов и папок, но без возможности получить потоки данных файлов и их атрибуты. Если расширение оболочки сообщит, что готово принять передаваемые файлы и папки, то при завершении процедуры перетаскивания программа WinRar распакует их во временную директорию и передаст список уже реально существующих файлов.

В этой процедуре можно дополнительно установить изображение и текст, которые будут отображаться на переносимом объекте. Делается это с помощью следующей процедуры:

procedure SetDropDescription(ADataObject: IDataObject; ADropImage: TdecDropImage; const AMessage, AInsert: UnicodeString);

Параметр ADropImage определяет тип изображения, которое будет отображаться на на переносимом объекте. Тип TdecDropImage определен следующим образом:

TdecDropImage = (diDefault, diNone, diCopy, diMove, diLink, diLabel, diWarning, diNoImage);
ЗначениеWinAPI флагВид изображенияОписание
diDefaultDROPIMAGE_INVALIDДополнительное изображение и текст определяются источником.
diNoneDROPIMAGE_NONEDROPIMAGE_NONEОперация перетаскивания данного объекта не возможна.
diCopyDROPIMAGE_COPYDROPIMAGE_COPYПосле операции перетаскивания будет произведена операция копирования перетаскиваемого объекта.
diMoveDROPIMAGE_MOVEDROPIMAGE_MOVEПосле операции перетаскивания будет произведена операция перемещения перетаскиваемого объекта.
diLinkDROPIMAGE_LINKDROPIMAGE_LINKПосле операции перетаскивания будет произведена операция создания ссылки на перетаскиваемый объект.
diLabelDROPIMAGE_LABELDROPIMAGE_LABELПосле операции перетаскивания будут изменены метаданные.
diWarningDROPIMAGE_WARNINGDROPIMAGE_WARNINGБыла выявлена проблема.
diNoImageDROPIMAGE_NOIMAGEДополнительное изображение и текст не отображаются.

Отображение и внешний вид дополнительных изображений зависит только от того, как данную функциональность поддерживает источник, с которого производится перетаскивание объекта. Значение diNoImage возможно использовать только в Windows начиная с версии Windows 7.

Параметры AMessage и AInsert определяют текст, которые будет отображаться рядом с дополнительным изображением. Строка AMessage может иметь значение, например, "Move to %1", а строка AInsert может иметь значение, например, "Documents". При этом итоговая строка, которая будет отображаться, будет иметь значение "Move to Documents".

function CanDropShellFileListToFile(ASourceDataObject: IDataObject; ASourceFileList: TdecShellFileList; const ADestFileName: UnicodeString; AOpenMode: DWORD; AAvailableEffects: TdecDropEffects; AShiftState: TShiftState): TdecDropEffect;

Метод аналогичен методу CanDropDataObjectToFile за исключением того, что в дополнение к интерфейсу IDataObject в параметре ASourceFileList передается уже созданный на основе интерфейса IDataObject объект класса TdecShellFileList.

function CanDropFileListToFile(ASourceDataObject: IDataObject; ASourceFileList: TStrings; const ADestFileName: UnicodeString; AOpenMode: DWORD; AAvailableEffects: TdecDropEffects; AShiftState: TShiftState): TdecDropEffect;

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

function DropDataObjectToFile(ASourceDataObject: IDataObject; const ADestFileName: UnicodeString; AOpenMode: DWORD; ADropEffect: TdecDropEffect): TdecDropEffect;

Функция должна попытаться произвести действие, описанное в параметре ADropEffect, над объектами, переданными в интерфейсе IDataObject, сброшенными на файл с именем ADestFileName, и вернуть тип действия, которые было реально произведено. Функция вызывается из реализации метода Drop интерфейса IDropTarget.

Объекты, переданные в интерфейсе IDataObject могут отличаться от объектов, переданных в интерфейсе IDataObject в метод CanDropDataObjectToFile. Поэтому НЕ кэшируйте список объектов в методе CanDropDataObjectToFile, а используйте данные, полученные из переданного интерфейса IDataObject!

Аналогично методу CanDropDataObjectToFile в данном метода также можно воспользоваться функцией CreateShellFileList для создания объекта класса TdecShellFileList.

Для информирования источника, с которого происходило перетаскивание объектов, о результате перетаскивания, в этом методе можно воспользоваться двумя дополнительными процедурами:

procedure SetLogicalPerformedDropEffect(ADataObject: IDataObject; ADropEffect: TdecDropEffect);
procedure SetPerformedDropEffect(ADataObject: IDataObject; ADropEffect: TdecDropEffect);

Обработчик используется также при формировании контекстного меню файла для создания команды Вставить, при этом в интерфейсе IDataObject передается текущее содержимое буфера обмена. В зависимости от того, какой командой было скопировано содержимого буфера обмена (Копировать или Вырезать), метод CanDropDataObjectToFileName может вызываться с различным значением параметра AAvailableEffects.

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

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