Как создать расширение оболочки Drop target
Обработчик Drop target позволяет определить действие, которое будет происходить при операции перетаскивания объектов на файл. Объектом может выступать не только файл, но и, например, текст, перетаскиваемый из текстового редакотра, или изображение, перетаскиваемого из графического редакотра. Также данный обработчик используется Проводником для формирования контекстного меню файла.
В библиотеке Shell Ace обработчик Drop target реализует следующие интерфейсы:
- IDropTarget
- IInitializeWithFile
- IPersistFile
После создания проекта расширения необходимо добавить в проект модуль с обработчиком Drop target. Для этого выберите соответствующую иконку на вкладке Shell extension:
Появится окно с предложением ввести имя класса и выбрать перекрываемые методы:
После нажатия на кнопку 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 флаг | Описание |
---|---|---|
deNone | DROPEFFECT_NONE | После операции перетаскивания не будет произведено никаких действий. |
deCopy | DROPEFFECT_COPY | После операции перетаскивания будет произведена операция копирования перетаскиваемого объекта. |
deMove | DROPEFFECT_MOVE | После операции перетаскивания будет произведена операция перемещения перетаскиваемого объекта. |
deLink | DROPEFFECT_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 флаг | Вид изображения | Описание |
---|---|---|---|
diDefault | DROPIMAGE_INVALID | Дополнительное изображение и текст определяются источником. | |
diNone | DROPIMAGE_NONE | Операция перетаскивания данного объекта не возможна. | |
diCopy | DROPIMAGE_COPY | После операции перетаскивания будет произведена операция копирования перетаскиваемого объекта. | |
diMove | DROPIMAGE_MOVE | После операции перетаскивания будет произведена операция перемещения перетаскиваемого объекта. | |
diLink | DROPIMAGE_LINK | После операции перетаскивания будет произведена операция создания ссылки на перетаскиваемый объект. | |
diLabel | DROPIMAGE_LABEL | После операции перетаскивания будут изменены метаданные. | |
diWarning | DROPIMAGE_WARNING | Была выявлена проблема. | |
diNoImage | DROPIMAGE_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 являются следующие методы:
- GetClassID
- FillProgIDList
- CanDropDataObjectToFileName
- DropDataObjectToFileName
Смотрите также:
- Что такое расширение оболочки
- Какие бывают расширения оболочки
- Как создать расширение оболочки
- Инициализация расширений оболочки
- Как создать расширение оболочки Context menu
- Как создать расширение оболочки Drag and drop context menu
- Как создать расширение оболочки Drop target
- Как создать расширение оболочки Icon
- Как создать расширение оболочки Info tip
- Как создать расширение оболочки Overlay icon
- Как создать расширение оболочки Preview
- Как создать расширение оболочки Property sheet
- Как создать расширение оболочки Property store
- Как создать расширение оболочки Thumbnail
- Как зарегистрировать расширение оболочки
- Как отлаживать расширение оболочки
- Использование логов