Расширения оболочки Windows

=== Расширения оболочки Windows ===
С каждой новой версией Windows, её оболочка (shell) приобретает всё больше и больше различных возможностей. Обычно эти возможности добавляются через расширения оболочки, которые позволяют разработчикам добавлять различные возможности в существующую оболочку Windows. Вот некоторые примеры расширений оболочки: Context Menus (меню, зависящее от объекта, на котором кликнули правой кнопкой мыши), Property Sheet Handlers (страницы в виде закладок, которые появляются в случае выбора пункта контексного меню Properties), Folder Customization, и т.д.
На сайте Microsoft доступно большое количество информации о расширениях оболочки, но эта информация мало полезна Delphi аудитории. Итак давайте рассмотрим расширение оболочки под названием "Всплывающие подсказки" (InfoTip), которые появляются в эксплорере, при наведении мышкой на файл.
=== Расширения оболочки - краткий обзор ===
Расширения оболочки существуют в виде In Process COM серверов. В ответ на определённые события оболочки проводник вызывает соответствующее расширение. Проводник очень специфически реагирует на различные функции в пределах оболочки. Первое, что делает Проводник - это проверяет модули, которые были зарегистрированы для определённого события и, если таковой существует, то загружает данный модуль.
Чтобы быть расширением оболочки, COM сервер должен включать в себя интерфейс, который определяет специфическое поведение для данного расширения, а так же он должен включать в себя интерфейс инициализации. Наконец, чтобы быть расширением оболочки, COM сервер должен следовать определённым в системе методам регистрации.
Следующая таблица представляет собой список всех существующих на сегодняшний день расширений оболочки, а так же их минимальных версий, участвующих интерфейсов и их описаний:
Тип 	Добавлено в 	Версия 	Используемые интерфейсы 	Описание
Context 	MenuFile class and shell’s object	Windows 95+ 	IContextMenu, IContextMenu2, или IContextMenu3	Позволяет добавлять новые пункты в контекстное меню объекта оболочки.
Right Drag and Drop	File class and shell’s object 	Windows 95+ 	IContextMenu, IContextMenu2, или IContextMenu3	Позволяет добавлять новые пункты в контекстное меню, при перетаскивании правой кнопкой мыши и отпускании файлов.
Drawing Shell Icons	File class and shell’s object 	Windows 95+ 	IExtractIcon 	Позволяет решить в данный момент, какая будет отображаться иконка для данного файла.
Property Sheet 	File class and shell’s object 	Windows 95+ 	IShellPropSheetExt 	Позволяет добавлять дополнительные страницы property sheet в диалог свойств файла. Так же это работает для Панели управления.
Left Drag and Drop 	File class and shell’s object 	Windows 95+ 	IDropTarget 	Позволяет решать - что делать с перетаскиваемым объектом (используя левую кнопку мыши) на другой объект в оболочке.
Clipboard 	File class and shell’s object 	Windows 95+ 	IDataObject 	Позволяет Вам определить, как объект скопирован и извлечён из буфера обмена.
File Hook 	 	Windows 95+ 	ICopyHook 	Позволяет контролировать некоторые файловые операции, которые происходят через оболочку. Вы можете разрешить или запретить их, но Вы не сможете получать уведомление об успешности операции или об ошибке.
Program Execution 	Explorer 	Desktop Update	IShellExecuteHook 	Позволяет перехватывать некоторые выполнения программ, которые происходят через оболочку.
Infotip 	File class and shell’s object 	Desktop Update	IQueryInfo 	Позволяет отображать короткие текстовые сообщения, когда курсор мышки находится на определённом файле.
Column 	Folders 	Windows 2000 	IColumnProvider 	Позволяет добавлять новую колонку в режиме отображения Details в Проводнике.
Icon Overlay 	Explorer 	Windows 2000 	IShellIconOverlay 	Позволяет определить собственные изображения, которые будут использоваться как иконки.
Search 	Explorer 	Windows 2000 	IContextMenu 	Позволяет добавить новую ячейку в меню "Найти" (в меню, открывающемся при нажатии на "Пуск").
Cleanup 	Cleanup Manager 	Windows 2000 	IEmptyVolumeCache2 	Позволяет добавить новую ячейку в Менеджер Очистки для очистки дискового пространства.
=== Всплывающие подсказки - Введение и обзор ===
Infotip-ы это всплывающие окна подсказки, которые появляются в случае, если курсор мышки находится над любым файлом. Если расширения для файла не было зарегистрировано, то будет высвечиваться окошко с подсказкой по умолчанию, однако Вы можете создать своё собственно расширение для отображения информации об определённом типе файла. Например, Office 2000 инсталлирует обработчики для MS Word и MS Excel, которые отображают Имя, Автора и заголовок из свойств документа. Расширения Infotip отличаются от других расширений оболочки по регистрации. Об этом мы поговорим позже, когда перейдём к регистрации нашего расширения Infotip.
==== Implementing Infotip Extensions ====
Расширение Infotip является In-Process (Inproc) COM Server. Это значит, что Infotip является обыкновенной Windows DLL, которая экспортирует необходимые методы, чтобы быть как обыкновенным элементом управления ActiveX. Расширение Infotip так же включает IQueryInfo и IPersistFile и должна самостоятельно регистрировать себя в реестре. В виду того, что IQueryInfo и IPersistFile являются интерфейсами, то они не содержат исходного кода своих методов. Поэтому наш объект включает в себя каждый метод, определённый в обоих интерфейсах; однако, некоторые из методов не являются необходимыми для нашего расширения Infotip, поэтому мы просто возвращаем E_NOTIMPL, чтобы показать, что они не осуществимы.
IQueryInfo обеспечивает отображение текста во всплывающем окошке и содержит два метода: GetInfoFlags - Получает информационные флаги. На текущий момент это метод не используется, поэтому возвращаем E_NOTIMPL. GetInfoTip - Получает текст Infotip-а.
GetInfoTip определена следующим образом:
function GetInfoTip(dwFlags: DWORD; var ppwszTip: PWideChar): HResult; stdcall;
* dwFlags - в данный момент не используется
* ppwszTip - Адрес указателя на строку Unicode, которая содержит текст подсказки.
Важное замечание
Параметр ppwszTip метода GetInfoTip - это указатель на строковый буфер Unicode, который содержит текст, отображаемый в всплывающем информационном поле. Этот буфер должен быть распределен, используя стандартную программу распределения памяти оболочки, потому что буфер распределен нашим приложением, но освобожден оболочкой. Чтобы быть уверенным, что всё пройдёт успешно, используйте SHGetMalloc для получения указателя на программу распределения памяти оболочки - объект IMalloc. Затем используйте метод Alloc из IMalloc-а для распределения необходимой памяти для буфера содержащего Unicode представление текста Infotip.
Исходник содержит стандартный код, который Вы можете использовать для всех расширений Infotip, которые Вы создадите.
IPersistFile это то, при помощи чего оболочка обеспечивает расширение информацией о файле, на котором находится курсор. В интерфейсе определены пять методов:
* IsDirty - проверяет объект на предмет изменений, сделанных в текущем файле. Наше расширение не требует данного метода, поэтому возвращаем E_NOTIMPL.
* Load - открывает указанный файл и инициализирует объект из содержимого файла. Мы будем использовать этот метод для получения имени файла, на котором находится курсор.
* Save - сохраняет объект в указанном файле. Мы его не используем и возвращаем E_NOTIMPL.
* SaveCompleted - уведомляет объект, о том, что он может быть переведён из режима NoScribble в режим Normal. Не используем, поэтому возвращаем E_NOTIMPL.
* GetCurFile - получает текущее имя файла, связанного с объектом. Тоже возвращаем E_NOTIMPL.
Load определена следующим образом:
function Load(pszFileName: PoleStr; dwMode: LongInt): HResult; stdcall;
* pszFileName - указатель на строку, содержащую абсолютный путь открываемого файла. Строка должна завершаться нулём.
* dwMode - содержит набор атрибутов для открытия файла.
Чтобы получить имя файла и его путь, мы будем использовать только IPersistFile; фактически мы не используем интерфейс для доступа к файлу, поэтому игнорируем флаги. Стандартная реализация метода Load сохраняет содержимое pszFileName в приватную переменную, которая будет использоваться в IQueryInfo::GetInfoTip для расположения файла.
=== Проект Delphi: Infotip ===
; Скачать исходник
* Скомпилированный проект (169KB) - Содержит DPRInfoTip.dll.
* Project Files (6KB) - Содержит исходные файлы проекта на Delphi.
* Registration File (1KB) - Содержит два файла регистрации (один для Win9x, а второй для Win2000).
Исходник содержит завершённое расширение оболочки Infotip. Infotip будет отображать имя файла, тип проекта (Программа или Библиотека), имя проекта (из файла исходника), и размер файла в байтах.
Для начала нам необходимо создать объект автоматизации и назвать его DPRInfoTip. Сперва кликните File | New... (для открытия архива объектов), затем на закладке ActiveX выберите ActiveX Library. Будет сгенерирована пустая библиотека ActiveX и экспортированы необходимые функции, требуемые для данного объекта автоматизации.
Далее, снова кликните File | New... и на закладке ActiveX выберите Automation Object. После этого откроется Automation Object Wizard, в котором необходимо ввести DPRInfoTip как имя CoClass (ниже показано, как выглядит этот диалог). Оставьте остальные опции по умолчанию и нажмите OK, будет сгенерирована основная Type Library и добавлен каркас для интерфейса IDPRInfoTip, который генерируется автоматически.
Как только файлы будут созданы, то следующее, что нам нужно сделать - это добавить поддержку для дополнительных интерфейсов, которые будут поддерживаться:
TDPRInfoTip = class(TAutoObject, IDPRInfoTip, IQueryInfo, IPersistFile, IPersist);
Обратите внимание: нам необходимо включить также и IPersist, потому что IPersistFile наследуется от IPersist.
Прилагаемый исходник можно использовать для всех расширений InfoTip. Единственное, что нужно изменить - это метод GenerateTip. Этот метод определяет текст, который будет отображён InfoTip.
В методе Initialization, мы вызываем SHGetMalloc, которая заставляет Windows распределить некоторое количество памяти, а затем возвращает указатель на неё в приватной (private) переменной pMalloc. В деструкторе устанавливаем pMalloc равной Nil. Это позволяет оболочке Windows выделять память при необходимости.
==== IPersistFile::Load ====
Когда мышка находится на файле, то оболочка вызывает метод Load, чтобы получить имя файла. В нашем случае имя файла хранится в приватной переменной FFile, поэтому оно будет доступно когда нам необходимо будет сгенерировать текст InfoTip.
 
function TDPRInfoTip.Load(pszFileName: POleStr; dwMode: Integer): HResult; 
begin 
 FFile := pszFileName; 
 Result := S_OK; 
end; 
Для всех остальных методов IPersistFile просто возвращаем E_NOTIMPL.
==== IQueryInfo::GetInfoTip ====
Когда оболочка готова отобразить InfoTip, она вызывает метод GetInfoTip для получения текста для отображения. В нашем случае, чтобы определить текст для отображения, вызывается метод GenerateTip.
=== Регистрация расширения Infotip ===
Регистрация происходит в два этапа:
1. При помощи regsvr32.exe регистрируется COM DLL (Пуск (Start)..Выполнить(Run))
 regsvr32 "C:\...\DPRInfoTip.dll"
2. Добавление ссылки на расширение (.dpr) в ключ реестра HKEY_CLASSES_ROOT.
По умолчанию значение для нового ключа должно быть CLSID объекта COM, который содержит расширение оболочки. Данное значение можно получить из файла Type Library, который был сгенерирован Delphi (имя файла оканчивается на "_TLB.pas"). Для нашего примера расширения CLSID назван CLASS_DPRInfoTip и содержит значение "{B20433A8-D083-11D4-993A-00D00912C440}".
Самый простой способ внести изменения в реестр - это сделать копию файла .REG, содержащуюся в исходниках проекта. Просто измените CLSID и расширение файла на необходимые значения.
Одно важное замечание:
Если Вы регистрируете расширение оболочки в Windows NT или 2000, то необходимо войти в систему с правами администратора.
Author: Larry J. Rutledge
Source: https://sources.ru/delphi/delphi_windows_shell_extensions_infotip.shtml
ID: 02400
Category:Статьи
Category:Учебники