Реализация базовых интерфейсов объектов папок
Процедура реализации расширения пространства имен аналогична процедуре для любого другого внутрипроцессного объекта объектной модели (COM). Все расширения должны поддерживать три основных интерфейса, которые предоставляют Windows Explorer с основными сведениями, необходимыми для отображения папок расширения в представлении дерева. Однако для полного использования возможностей обозревателя Windows расширение также должно предоставлять один или несколько необязательных интерфейсов, поддерживающих более сложные функции, такие как контекстные меню или перетаскивание, и предоставить представление папки.
В этом документе описывается, как реализовать основные и необязательные интерфейсы, которые Windows Explorer вызывает сведения о содержимом расширения. Сведения о реализации представления папок и настройке обозревателя Windows см. в разделе "Реализация представления папок".
- Базовая реализация и регистрация
- Обработка ПИН-кодов
- Реализация основных интерфейсов
- Реализация необязательных интерфейсов
- Работа с реализацией представления папок оболочки по умолчанию
Базовая реализация и регистрация
В качестве внутрипроцессного COM-сервера библиотека DLL должна предоставлять несколько стандартных функций и интерфейсов:
Эти функции и интерфейсы реализуются так же, как и для большинства других COM-объектов. Дополнительные сведения см. в документации по COM.
Регистрация расширения
Как и во всех COM-объектах, необходимо создать guid идентификатора класса (CLSID) для расширения. Зарегистрируйте объект, создав подраздел HKEY_CLASSES_ROOT\CLSID с именем CLSID расширения. Библиотека DLL должна быть зарегистрирована как внутрипроцессный сервер и должна указывать модель потоков квартиры. Вы можете настроить поведение корневой папки расширения, добавив различные подразделы и значения в ключ CLSID расширения.
Некоторые из этих значений применяются только к расширениям с виртуальными точками соединения. Эти значения не применяются к расширениям, точки соединения которых являются папками файловой системы. Дополнительные сведения см. в разделе "Указание расположения расширения пространства имен". Чтобы изменить поведение расширения с виртуальной точкой соединения, добавьте одно или несколько следующих значений в ключ CLSID расширения:
- WantsFORPARSING. Имя синтаксического анализа для расширения с виртуальной точкой соединения обычно имеет форму ::{GUID}. Расширения этого типа обычно содержат виртуальные элементы. Однако некоторые расширения, такие как "Мои документы", фактически соответствуют папкам файловой системы, даже если они имеют виртуальные точки соединения. Если расширение представляет объекты файловой системы таким образом, можно задать значение WantsFORPARSING. Windows Explorer запросит имя синтаксического анализа корневой папки, вызвав метод IShellFolder объекта папки::GetDisplayNameOf с параметром uFlags для SHGDN_FORPARSING и pidl, установленным на один пустой указатель на список идентификаторов элементов (PIDL). Пустой PIDL содержит только признак конца. Затем метод должен вернуть имя синтаксического анализа корневой папки ::{GUID}.
- HideFolderVerbs. Команды, зарегистрированные в HKEY_CLASSES_ROOT\Folder, обычно связаны со всеми расширениями. Они отображаются в контекстном меню расширения и могут вызываться ShellExecute. Чтобы предотвратить связь любой из этих команд с расширением, задайте значение HideFolderVerbs.
- HideAsDelete. Если пользователь пытается удалить расширение, Windows Explorer вместо этого скрывает расширение.
- HideAsDeletePerUser. Это значение действует так же, как HideAsDelete, но на уровне пользователя. Расширение скрыто только для тех пользователей, которые пытались удалить его. Расширение отображается для всех остальных пользователей.
- QueryForOverlay. Задайте это значение, чтобы указать, что значок корневой папки может иметь наложение значка. Объект папки должен поддерживать интерфейс IShellIconOverlay . Прежде чем Windows Explorer отобразит значок корневой папки, он запросит значок наложения, вызвав один из двух методов IShellIconOverlay с pidlItem, установленным в пустой PIDL.
Остальные значения и подразделы применяются ко всем расширениям:
- Чтобы указать отображаемое имя папки точки соединения расширения, задайте для подключа CLSID расширения значение по умолчанию соответствующей строкой.
- При наведении курсора на папку обычно отображается подсказка, описывающая содержимое папки. Чтобы предоставить подсказку для корневой папки расширения, создайте значение InfoTip REG_SZ для ключа CLSID расширения и задайте для него соответствующую строку.
- Чтобы указать настраиваемый значок корневой папки расширения, создайте подраздел подраздела подраздела CLSID расширения с именем DefaultIcon. Задайте значение по умолчанию DefaultIconзначением REG_SZ , содержащим имя файла, содержащего значок, запятой, за которой следует знак минуса, за которым следует индекс значка в этом файле.
- По умолчанию контекстное меню корневой папки расширения будет содержать элементы, определенные в разделеHKEY_CLASSES_ROOT\Folder. При установке соответствующих флагов SFGAO_XXX добавляются элементы " Удалить", "Переименовать" и "Свойства ". Вы можете добавить другие элементы в контекстное меню корневой папки или переопределить существующие элементы так же, как и для типа файла. Создайте подраздел оболочки под ключом CLSID расширения и определите команды, как описано в разделе "Расширение контекстных меню".
- Если вам нужен более гибкий способ обработки контекстного меню корневой папки, можно реализовать обработчик контекстного меню. Чтобы зарегистрировать обработчик контекстного меню, создайте ключ ShellEx под ключом CLSID расширения. Зарегистрируйте CLSID обработчика, как и для обычных обработчиков создания расширений оболочки.
- Чтобы добавить страницу на лист свойств корневой папки, присвойте папке атрибут SFGAO_HASPROPSHEET и реализуйте обработчик листа свойств. Чтобы зарегистрировать обработчик страниц свойств, создайте ключ ShellEx под ключом CLSID расширения. Зарегистрируйте CLSID обработчика, как и для обычных обработчиков создания расширений оболочки.
- Чтобы указать атрибуты корневой папки, добавьте подраздел ShellFolder в подраздел CLSID расширения. Создайте значение атрибутов и присвойте ему соответствующее сочетание флагов SFGAO_XXX .
В следующей таблице перечислены некоторые часто используемые атрибуты для корневых папок.
Флаг | Значение | Описание: |
---|---|---|
SFGAO_FOLDER | 0x20000000 | Корневая папка расширения содержит один или несколько элементов. |
SFGAO_HASSUBFOLDER | 0x80000000 | Корневая папка расширения содержит одну или несколько вложенных папок. Windows Explorer поместит знак "плюс" (+) рядом со значком папки. |
SFGAO_CANDELETE | 0x00000020 | Пользователь может удалить корневую папку расширения. Контекстное меню папки будет содержать элемент Delete . Этот флаг должен быть установлен для точек соединения, размещенных в одной из виртуальных папок. |
SFGAO_CANRENAME | 0x00000010 | Корневая папка расширения может быть переименована пользователем. Контекстное меню папки будет иметь элемент "Переименовать ". |
SFGAO_HASPROPSHEET | 0x00000040 | Корневая папка расширения содержит страницу свойств. Контекстное меню папки будет иметь элемент "Свойства ". Чтобы предоставить лист свойств, необходимо реализовать обработчик листа свойств. Зарегистрируйте обработчик в ключе CLSID расширения, как описано выше. |
В следующем примере показана запись реестра CLSID для расширения с отображаемым именем MyExtension. Расширение имеет пользовательский значок, который содержится в библиотеке DLL расширения с индексом 1. Задаются атрибуты SFGAO_FOLDER, SFGAO_HASSUBFOLDER и SFGAO_CANDELETE .
HKEY_CLASSES_ROOT
CLSID
{Extension CLSID}
(Default) = MyExtension
InfoTip = Some appropriate text
DefaultIcon
(Default) = c:\MyDir\MyExtension.dll,-1
InProcServer32
(Default) = c:\MyDir\MyExtension.dll
ThreadingModel = Apartment
ShellFolder
Attributes = 0xA00000020
Обработка ПИН-кодов
Каждый элемент в пространстве имен оболочки должен иметь уникальный PIDL. Windows Explorer назначает PIDL корневой папке и передает значение расширению во время инициализации. После этого расширение отвечает за назначение правильно созданного PIDL каждому из его объектов и предоставление этих PID-адресов для Windows Explorer по запросу. Когда оболочка использует PIDL для идентификации одного из объектов расширения, расширение должно иметь возможность интерпретировать PIDL и идентифицировать конкретный объект. Расширение также должно назначить отображаемое имя и имя синтаксического анализа каждому объекту. Так как PID-файлы используются практически каждым интерфейсом папок, расширения обычно реализуют один диспетчер PIDL для обработки всех этих задач.
Термин PIDL является коротким для структуры ITEMIDLIST или указателя на такую структуру в зависимости от контекста. Как было объявлено, структура ITEMIDLIST имеет один элемент, структуру SHITEMID . Структура ITEMIDLIST объекта на самом деле представляет собой упакованный массив из двух или более структур SHITEMID . Порядок этих структур определяет путь через пространство имен так же, как c:\MyDirectory\MyFile определяет путь через файловую систему. Как правило, PIDL объекта состоит из ряда структур SHITEMID , соответствующих папкам, определяющим путь к пространству имен, за которым следует структура SHITEMID объекта, за которой следует признак конца.
Признак конца — это структура SHITEMID с элементом CB , имеющим значение NULL. Признак конца необходим, так как число структур SHITEMID в PIDL объекта зависит от расположения объекта в пространстве имен оболочки и начальной точки пути. Кроме того, размер различных структур SHITEMID может отличаться. При получении PIDL у вас нет простого способа определения его размера или даже общего числа структур SHITEMID . Вместо этого необходимо "прогулять" упакованный массив, структуру по структуре, пока не достигнете конца.
Чтобы создать PIDL, приложение должно:
- Создайте структуру SHITEMID для каждого из его объектов.
- Соберите соответствующие структуры SHITEMID в PIDL.
Создание структуры SHITEMID
Структура SHITEMID объекта однозначно идентифицирует объект в своей папке. Фактически тип PIDL, используемый многими методами IShellFolder , состоит только из структуры SHITEMID объекта, за которой следует признак конца. Определение структуры SHITEMID :
typedef struct _SHITEMID {
USHORT cb;
BYTE abID[1];
} SHITEMID, * LPSHITEMID;
Член abID — это идентификатор объекта. Так как длина abID не определена и может отличаться, член cb задается в соответствии с размером структуры SHITEMID в байтах.
Так как ни длина, ни содержимое abID не стандартизированы, вы можете использовать любую схему, которую вы хотите назначить значения abID объектам. Единственное требование заключается в том, что в одной папке не может быть двух объектов с одинаковыми значениями. Однако по соображениям производительности структура SHITEMID должна быть выровнена по DWORD. Другими словами, следует создать значения abID таким образом, чтобы cb был целочисленным кратным из 4.
Как правило, abID указывает на определяемую расширением структуру. Помимо идентификатора объекта, эта структура часто используется для хранения различных связанных сведений, таких как тип объекта или атрибуты. Затем объекты папок расширения могут быстро извлекать сведения из PIDL, а не запрашивать их.
Примечание
Одним из наиболее важных аспектов проектирования структуры данных для PIDL является обеспечение сохраняемой и переносимой структуры. В контексте PIDL смысл этих терминов:
- Сохраняемая. Система часто размещает PID-файлы в различных типах долгосрочного хранения, таких как ярлыки файлов. Затем эти PID-файлы можно восстановить из хранилища позже, возможно, после перезагрузки системы. PiDL, восстановленный из хранилища, по-прежнему должен быть допустимым и значимым для вашего расширения. Это требование означает, например, что не следует использовать указатели или дескрипторы в структуре PIDL. PID-файлы, содержащие этот тип данных, обычно будут бессмысленными, когда система позже восстановит их из хранилища.
- Переносные. PiDL должен оставаться значимым при переносе с одного компьютера на другой. Например, PIDL можно записать в файл ярлыка, скопировать его на гибкий диск и перенести на другой компьютер. Этот PIDL по-прежнему должен быть значимым для вашего расширения, работающего на втором компьютере. Например, чтобы убедиться, что ПИН-коды являются переносимыми, используйте символы ANSI или Юникод явным образом. Избегайте таких типов данных, как TCHAR или LPTSTR. Если вы используете эти типы данных, piDL, созданный на компьютере с версией расширения Юникода, не будет прочитан версией ANSI этого расширения, работающего на другом компьютере.
В следующем объявлении показан простой пример структуры данных.
typedef struct tagMYPIDLDATA {
USHORT cb;
DWORD dwType;
WCHAR wszDisplayName[40];
} MYPIDLDATA, *LPMYPIDLDATA;
Для элемента CB задается размер структуры MYPIDLDATA . Этот элемент делает MYPIDLDATA допустимой структурой SHITEMID и само по себе. Остальные члены эквивалентны члену abID структуры SHITEMID и содержат закрытые данные. Элемент dwType — это определяемое расширением значение, указывающее тип объекта. В этом примере dwType имеет значение TRUE для папок, а в противном случае — FALSE . Этот член позволяет, например, быстро определить, является ли объект папкой или нет. Элемент wszDisplayName содержит отображаемое имя объекта. Так как отображаемое имя не присваивается двум разным объектам в одной папке, отображаемое имя также служит идентификатором объекта. В этом примере параметр wszDisplayName имеет значение 40 символов, чтобы гарантировать, что структура SHITEMID будет выровнена по DWORD. Чтобы ограничить размер ПИН-кодов, можно использовать массив символов переменной длины и соответствующим образом настроить значение cb. Поместите строку отображения с достаточным количеством символов "\0", чтобы сохранить выравнивание DWORD структуры. Другие члены, которые могут быть полезны для вставки в структуру, включают размер объекта, атрибуты или имя синтаксического анализа.
Создание PIDL
Определив структуры SHITEMID для объектов, их можно использовать для создания PIDL. PID-файлы можно создать для различных целей, но большинство задач используют один из двух типов PIDL. Самый простой, одноуровневый PIDL, идентифицирует объект относительно родительской папки. Этот тип PIDL используется многими методами IShellFolder . Одноуровневый PIDL содержит структуру SHITEMID объекта, за которой следует признак конца. Полный PIDL определяет путь через иерархию пространства имен от рабочего стола к объекту. Этот тип PIDL начинается на рабочем столе и содержит одну структуру SHITEMID для каждой папки в пути, за которой следует объект и признак конца. Полный PIDL однозначно идентифицирует объект в пределах всего пространства имен оболочки.
Самый простой способ создания PIDL — работать непосредственно со структурой ITEMIDLIST . Создайте структуру ITEMIDLIST , но выделите достаточно памяти для хранения всех структур SHITEMID . Адрес этой структуры будет указывать на начальную структуру SHITEMID . Определите значения для членов этой начальной структуры, а затем добавьте столько дополнительных структур SHITEMID , сколько необходимо, в соответствующем порядке. В следующей процедуре описано, как создать одноуровневый PIDL. Он содержит две структуры SHITEMID — структуру MYPIDLDATA , за которой следует признак конца:
- Используйте функцию CoTaskMemAlloc для выделения памяти для PIDL. Выделите достаточно памяти для частных данных, а также USHORT (два байта) для признака конца. Приведение результата к LPMYPIDLDATA.
- Задайте для элемента CB первой структуры MYPIDLDATA размер этой структуры. В этом примере задается значение cb sizeof(MYPIDLDATA). Если вы хотите использовать структуру переменной длины, необходимо вычислить значение cb.
- Назначьте соответствующие значения членам закрытых данных.
- Вычисление адреса следующей структуры SHITEMID . Приведение адреса текущей структуры MYPIDLDATA к LPBYTE и добавление этого значения к значению cb , определенному на шаге 3.
- В этом случае следующая структура SHITEMID является признаком конца. Присвойте члену cb структуры значение 0.
Для более длинных ПИН-адресов выделите достаточно памяти и повторите шаги 3–5 для каждой дополнительной структуры SHITEMID .
Следующий пример функции принимает тип объекта и отображаемое имя и возвращает одноуровневый PIDL объекта. Функция предполагает, что отображаемое имя, включая завершающий пустой символ, не превышает число символов, объявленных для структуры MYPIDLDATA . Если это предположение окажется ошибочным, функция StringCbCopyW усетит отображаемое имя. Переменная g_pMalloc — это указатель IMalloc , созданный в другом месте и хранящийся в глобальной переменной.
LPITEMIDLIST CreatePIDL(DWORD dwType, LPCWSTR pwszDisplayName)
{
LPMYPIDLDATA pidlOut;
USHORT uSize;
pidlOut = NULL;
//Calculate the size of the MYPIDLDATA structure.
uSize = sizeof(MYPIDLDATA);
// Allocate enough memory for the PIDL to hold a MYPIDLDATA structure
// plus the terminator
pidlOut = (LPMYPIDLDATA)m_pMalloc->Alloc(uSize + sizeof(USHORT));
if(pidlOut)
{
//Assign values to the members of the MYPIDLDATA structure
//that is the PIDL's first SHITEMID structure
pidlOut->cb = uSize;
pidlOut->dwType = dwType;
hr = StringCbCopyW(pidlOut->wszDisplayName,
sizeof(pidlOut->wszDisplayName), pwszDisplayName);
// TODO: Add error handling here to verify the HRESULT returned
// by StringCbCopyW.
//Advance the pointer to the start of the next SHITEMID structure.
pidlOut = (LPMYPIDLDATA)((LPBYTE)pidlOut + pidlOut->cb);
//Create the terminating null character by setting cb to 0.
pidlOut->cb = 0;
}
return pidlOut;
Полный КОД PIDL должен иметь структуры SHITEMID для каждого объекта из рабочего стола в объект. Расширение получает полный piDL для корневой папки, когда оболочка вызывает IPersistFolder::Initialize. Чтобы создать полный PIDL для объекта, возьмите PIDL, назначенный оболочке корневой папке, и добавьте структуры SHITEMID , необходимые для переноса из корневой папки в объект.
Интерпретация ПИН-кодов
Когда оболочка или приложение вызывает один из интерфейсов расширения для запроса сведений об объекте, обычно он определяет объект по PIDL. Некоторые методы, такие как IShellFolder::GetUIObjectOf, используют PID-списки, относящиеся к родительской папке и просты в интерпретации. Однако расширение, вероятно, также получит полные ПИН-коды. Затем диспетчер PIDL должен определить, какие объекты, на которые ссылается PIDL.
Что усложняет задачу связывания объекта с полным идентификатором PIDL, заключается в том, что одна или несколько начальных структур SHITEMID в PIDL могут принадлежать объектам, которые находятся за пределами расширения в пространстве имен оболочки. Вы не можете интерпретировать смысл члена abID этих структур. Расширение должно выполняться так, чтобы перейти к списку структур SHITEMID , пока не достигнете структуры, соответствующей корневой папке. С этого момента вы узнаете, как интерпретировать информацию в структурах SHITEMID .
Чтобы перейти к PIDL, примите первое значение cb и добавьте его в адрес PIDL, чтобы перейти к началу следующей структуры SHITEMID . Затем он будет указывать на cb-член этой структуры, который можно использовать для продвижения указателя к началу следующей структуры SHITEMID и т. д. Каждый раз, когда вы перемещаете указатель, изучите структуру SHITEMID , чтобы определить, достигли ли вы корень пространства имен расширения.
Реализация основных интерфейсов
Как и во всех COM-объектах, реализация расширения в значительной степени является вопросом реализации коллекции интерфейсов. В этом разделе рассматриваются три основных интерфейса, которые должны быть реализованы всеми расширениями. Они используются для инициализации и предоставления Windows Explorer основных сведений о содержимом расширения. Эти интерфейсы, а также представление папок, необходимы для функционального расширения. Однако для полного использования функций обозревателя Windows большинство расширений также реализуют один или несколько необязательных интерфейсов.
Интерфейс IPersistFolder
Интерфейс IPersistFolder вызывается для инициализации нового объекта папки. Метод IPersistFolder::Initialize назначает полный PIDL новому объекту. Сохраните этот PIDL для последующего использования. Например, объект папки должен использовать этот PIDL для создания полных идентификаторов PID для дочерних элементов объекта. Создатель объекта папки также может вызвать IPersist::GetClassID для запроса CLSID объекта.
Как правило, объект папки создается и инициализируется методом IShellFolder::BindToObject своей родительской папки. Однако при просмотре расширения Windows Explorer создает и инициализирует объект корневой папки расширения. PIDL, получаемый объектом корневой папки через IPersistFolder::Initialize , содержит путь от рабочего стола к корневой папке, которую необходимо создать для расширения полные ИДЕНТИФИКАТОРЫ.
Интерфейс IShellFolder
Оболочка обрабатывает расширение как иерархически упорядоченную коллекцию объектов папок. Интерфейс IShellFolder является ядром любой реализации расширения. Он представляет объект папки и предоставляет Windows Explorer с большой частью информации, необходимой для отображения содержимого папки.
IShellFolder обычно является единственным интерфейсом папок, кроме IPersistFolder , который напрямую предоставляется объектом папки. Хотя Windows Explorer использует различные обязательные и необязательные интерфейсы для получения сведений о содержимом папки, он получает указатели на эти интерфейсы через IShellFolder.
Windows Explorer получает CLSID корневой папки расширения различными способами. Дополнительные сведения см. в разделе "Указание расположения расширения пространства имен " или отображение Self-Contained представления расширения пространства имен. Windows Explorer затем использует этот CLSID для создания и инициализации экземпляра корневой папки и запроса интерфейса IShellFolder. Расширение создает объект папки для представления корневой папки и возвращает интерфейс IShellFolder объекта. Большая часть остальной части взаимодействия между расширением и Windows Explorer выполняется через IShellFolder. Windows Explorer вызывает IShellFolder для:
- Запрос объекта, который может перечислять содержимое корневой папки.
- Получите различные типы сведений о содержимом корневой папки.
- Запрос объекта, предоставляющего один из необязательных интерфейсов. Затем эти интерфейсы можно запрашивать для получения дополнительных сведений, таких как значки или контекстные меню.
- Запрос объекта папки, представляющего вложенную папку корневой папки.
Когда пользователь открывает вложенную папку корневой папки, Windows Explorer вызывает IShellFolder::BindToObject. Расширение создает и инициализирует новый объект папки для представления вложенной папки и возвращает его интерфейс IShellFolder . Windows Explorer затем вызывает этот интерфейс для различных типов сведений и т. д., пока пользователь не решит перейти в другое место в пространстве имен оболочки или закрыть Windows Explorer.
В оставшейся части этого раздела кратко рассматриваются более важные методы IShellFolder и способы их реализации.
EnumObjects
Перед отображением содержимого папки в представлении дерева Windows Explorer сначала определите, какая папка содержится, вызвав метод IShellFolder::EnumObjects. Этот метод создает стандартный объект перечисления OLE, предоставляющий интерфейс IEnumIDList и возвращающий этот указатель интерфейса. Интерфейс IEnumIDList позволяет Windows Explorer получать PID-списки всех объектов, содержащихся в папке. Затем эти PID-адреса используются для получения сведений об объектах, содержащихся в папке. Дополнительные сведения см. в разделе "Интерфейс IEnumIDList".
Примечание
Метод IEnumIDList::Next должен возвращать только ИДЕНТИФИКАТОРЫ, относящиеся к родительской папке. PIDL должен содержать только структуру SHITEMID объекта, за которой следует признак конца.
CreateViewObject
Перед отображением содержимого папки Windows Explorer вызывает этот метод для запроса указателя на интерфейс IShellView. Этот интерфейс используется Windows Explorer для управления представлением папок. Создайте объект представления папок и верните его интерфейс IShellView .
Метод IShellFolder::CreateViewObject также вызывается для запроса одного из необязательных интерфейсов, таких как IContextMenu, для самой папки. Реализация этого метода должна создать объект, предоставляющий запрошенный интерфейс и возвращающий указатель интерфейса. Если Windows Explorer требуется дополнительный интерфейс для одного из объектов, содержащихся в папке, он вызовет IShellFolder::GetUIObjectOf.
GetUIObjectOf
Хотя основные сведения о содержимом папки доступны с помощью методов IShellFolder, расширение также может предоставить Windows Explorer с различными типами дополнительных сведений. Например, можно указать значки для содержимого папки или контекстного меню объекта. Windows Explorer вызывает метод IShellFolder::GetUIObjectOf, чтобы попытаться получить дополнительные сведения об объекте, содержавшемся в папке. Windows Explorer указывает объект, для которого требуется информация, и iiD соответствующего интерфейса. Затем объект папки создает объект, предоставляющий запрошенный интерфейс и возвращающий указатель интерфейса.
Если расширение позволяет пользователям передавать объекты с помощью перетаскивания или буфера обмена, Windows Explorer вызовет IShellFolder::GetUIObjectOf для запроса интерфейса IDataObject или IDropTarget. Дополнительные сведения см. в разделе "Передача объектов оболочки" с перетаскиванием и буфером обмена.
Windows Explorer вызывает IShellFolder::CreateViewObject, если требуется такая же информация о самой папке.
BindToObject
Windows Explorer вызывает метод IShellFolder::BindToObject, когда пользователь пытается открыть одну из вложенных папок расширения. Если для riid задано значение IID_IShellFolder, необходимо создать и инициализировать объект папки, представляющий вложенную папку, и вернуть интерфейс IShellFolder объекта.
Примечание
В настоящее время Windows Explorer вызывает этот метод только для запроса интерфейса IShellFolder. Однако не предполагайте, что это всегда будет так. Перед продолжением следует всегда проверять значение riid .
GetDisplayNameOf
Windows Explorer вызывает метод IShellFolder::GetDisplayNameOf для преобразования PIDL одного из объектов папки в имя. Этот PIDL должен быть относительным к родительской папке объекта. Другими словами, она должна содержать одну структуру, не содержащуюNULLSHITEMID. Так как существует несколько возможных способов именовать объекты, Windows Explorer указывает тип имени, задав один или несколько флагов SHGDNF в параметре uFlags. Одно из двух значений , SHGDN_NORMAL или SHGDN_INFOLDER, будет задано, чтобы указать, должно ли имя быть относительно папки или относительно рабочего стола. Можно задать одно из трех других значений, SHGDN_FOREDITING, SHGDN_FORADDRESSBAR или SHGDN_FORPARSING, чтобы указать, для чего будет использоваться имя.
Необходимо вернуть имя в виде структуры STRRET . Если SHGDN_FOREDITING, SHGDN_FORADDRESSBAR и SHGDN_FORPARSING не заданы, верните отображаемое имя объекта. Если установлен флаг SHGDN_FORPARSING, Windows Explorer запрашивает имя синтаксического анализа. Имена синтаксического анализа передаются в IShellFolder::P arseDisplayName для получения PIDL объекта, даже если он может находиться на одном или нескольких уровнях ниже текущей папки в иерархии пространства имен. Например, имя синтаксического анализа объекта файловой системы — это его путь. Полный путь любого объекта в файловой системе можно передать методу IShellFolder::P arseDisplayName рабочего стола, и он вернет полный PIDL объекта.
Хотя имена синтаксического анализа являются текстовыми строками, они не обязательно должны включать отображаемое имя. Имена синтаксического анализа следует назначать на основе наиболее эффективной работы при вызове IShellFolder::P arseDisplayName . Например, многие виртуальные папки оболочки не входят в файловую систему и не имеют полного пути. Вместо этого каждой папке назначается GUID, а имя синтаксического анализа принимает форму ::{GUID}. Независимо от того, какую схему вы используете, она должна иметь возможность надежно "кругового пути". Например, если вызывающий объект передает имя синтаксического анализа в IShellFolder::P arseDisplayName для получения PIDL объекта, а затем передает его в IShellFolder::GetDisplayNameOf с набором флагов SHGDN_FORPARSING , вызывающий объект должен восстановить исходное имя синтаксического анализа.
GetAttributesOf
Windows Explorer вызывает метод IShellFolder::GetAttributesOf, чтобы определить атрибуты одного или нескольких элементов, содержащихся в объекте папки. Значение cidl дает количество элементов в запросе, а aPidl указывает на список своих PID-адресов.
Так как тестирование некоторых атрибутов может занять много времени, Windows Explorer обычно ограничивает запрос подмножеством доступных флагов, задав их значения в rfgInOut. Метод должен проверять только те атрибуты, флаги которых заданы в rfgInOut. Оставьте допустимые флаги установленными и очистите оставшуюся часть. Если в запрос входит несколько элементов, задайте только те флаги, которые применяются ко всем элементам.
Примечание
Атрибуты должны быть правильно заданы для правильного отображения элемента. Например, если элемент является папкой, содержащей вложенные папки, необходимо задать флаг SFGAO_HASSUBFOLDER . В противном случае Windows Explorer не будет отображать значок +рядом со значком элемента в представлении дерева.
ParseDisplayName
Метод IShellFolder::P arseDisplayName в некотором смысле представляет собой зеркальное изображение IShellFolder::GetDisplayNameOf. Чаще всего этот метод используется для преобразования имени синтаксического анализа объекта в связанный PIDL. Имя синтаксического анализа может ссылаться на любой объект, который находится под папкой в иерархии пространства имен. Возвращенный PIDL относится к объекту папки, который предоставляет метод и обычно не является полным. Другими словами, хотя PIDL может содержать несколько структур SHITEMID , первым будет либо сам объект, либо первая вложенная папка в пути от папки к объекту. Вызывающий объект должен добавить этот PIDL в полный КОД PIDL папки, чтобы получить полный PIDL для объекта.
IShellFolder::P arseDisplayName также можно вызвать для запроса атрибутов объекта. Поскольку определение всех применимых атрибутов может занять много времени, вызывающий объект установит только те флаги SFGAO_XXX , которые представляют сведения, интересующие вызывающего объекта. Необходимо определить, какие из этих атрибутов верны для объекта, и очистить остальные флаги.
Интерфейс IEnumIDList
Если Windows Explorer необходимо перечислить объекты, содержащиеся в папке, он вызывает IShellFolder::EnumObjects. Объект папки должен создать объект перечисления, предоставляющий интерфейс IEnumIDList и возвращающий этот указатель интерфейса. Windows Explorer обычно использует IEnumIDList для перечисления PID-списков всех объектов, содержащихся в папке.
IEnumIDList — это стандартный интерфейс перечисления OLE и реализован обычным способом. Помните, однако, что возвращаемые ИДЕНТИФИКАТОРЫ должны быть относительны к папке и содержать только структуру SHITEMID объекта и признак конца.
Реализация необязательных интерфейсов
Существует ряд необязательных интерфейсов оболочки, которые могут поддерживать объекты папок расширения. Многие из них, такие как IExtractIcon, позволяют настраивать различные аспекты того, как пользователь просматривает расширение. Другие, такие как IDataObject, позволяют вашему расширению поддерживать такие функции, как перетаскивание.
Ни один из необязательных интерфейсов не предоставляется непосредственно объектом папки. Вместо этого Windows Explorer вызывает один из двух методов IShellFolder для запроса интерфейса:
- Windows Explorer вызывает объект папки IShellFolder::GetUIObjectOf, чтобы запросить интерфейс для одного из объектов, содержащихся в папке.
- Windows Explorer вызывает объект папки IShellFolder::CreateViewObject, чтобы запросить интерфейс для самой папки.
Чтобы предоставить сведения, объект папки создает объект, предоставляющий запрошенный интерфейс и возвращающий указатель интерфейса. Windows Explorer затем вызывает этот интерфейс для получения необходимых сведений. В этом разделе рассматриваются наиболее часто используемые необязательные интерфейсы.
IExtractIcon
Windows Explorer запрашивает интерфейс IExtractIcon перед отображением содержимого папки. Интерфейс позволяет расширению указывать пользовательские значки для объектов, содержащихся в папке. В противном случае будут использоваться стандартные значки файлов и папок. Чтобы предоставить пользовательский значок, создайте объект извлечения значков, который предоставляет IExtractIcon и возвращает указатель на этот интерфейс. Дополнительные сведения см. в справочной документации по IExtractIcon или создании обработчиков значков.
IContextMenu
Когда пользователь щелкает объект правой кнопкой мыши, Windows Explorer запрашивает интерфейс IContextMenu. Чтобы предоставить контекстные меню для объектов, создайте объект обработчика меню и верните его интерфейс IContextMenu .
Процедуры создания объекта обработчика меню очень похожи на процедуры создания расширения оболочки обработчика меню. Дополнительные сведения см. в справочнике по созданию обработчиков контекстного меню или IContextMenu, IContextMenu2 или IContextMenu3 .
IQueryInfo
Windows Explorer вызывает интерфейс IQueryInfo для получения текстовой строки подсказки.
IDataObject и IDropTarget
Когда объекты отображаются в обозревателе Windows, объект папки не имеет прямого способа узнать, когда пользователь пытается вырезать, копировать или перетаскивать объект. Вместо этого Windows Explorer запрашивает интерфейс IDataObject. Чтобы разрешить перенос объекта, создайте объект данных и верните указатель на его интерфейс IDataObject .
Аналогичным образом пользователь может попытаться удалить объект данных в представлении обозревателя Windows одного из ваших объектов, например значок или путь адресной строки. Windows Explorer запрашивает интерфейс IDropTarget. Чтобы разрешить удаление объекта данных, создайте объект, предоставляющий интерфейс IDropTarget и возвращающий указатель интерфейса.
Обработка передачи данных является одним из более сложных аспектов написания расширений пространства имен. Подробное обсуждение см. в разделе "Передача объектов оболочки" с перетаскиванием и буфером обмена.
Работа с реализацией представления папок оболочки по умолчанию
Источники данных, использующие объект представления папок оболочки по умолчанию (DefView), должны реализовать следующие интерфейсы:
При необходимости они также могут реализовать IPersistFolder3.