Поделиться через


Реализация интерфейсов объектов базовых папок

Процедура реализации расширения пространства имен аналогична процедуре для любого другого объекта объектной объектной модели компонента (COM). Все расширения должны поддерживать три основных интерфейса, которые предоставляют проводнику Windows базовые сведения, необходимые для отображения папок расширения в представлении дерева. Однако для полного использования возможностей проводника Windows расширение также должно предоставлять один или несколько необязательных интерфейсов, поддерживающих более сложные функции, такие как контекстные меню или перетаскивание, и предоставить представление папок.

В этом документе описывается реализация основных и необязательных интерфейсов, которые обозреватель Windows вызывает сведения о содержимом расширения. Сведения о реализации представления папок и настройке обозревателя Windows см. в разделе "Реализация представления папок".

Базовая реализация и регистрация

В качестве встроенного COM-сервера библиотека DLL должна предоставлять несколько стандартных функций и интерфейсов:

Эти функции и интерфейсы реализуются так же, как и для большинства других ОБЪЕКТОВ COM. Дополнительные сведения см. в документации com.

Регистрация расширения

Как и во всех COM-объектах, необходимо создать GUID идентификатора класса (CLSID) для расширения. Зарегистрируйте объект, создав подключ HKEY_CLASSES_ROOT\CLSID с именем CLSID расширения. Библиотека DLL должна быть зарегистрирована в качестве внутреннего сервера и должна указывать модель потоков квартиры. Вы можете настроить поведение корневой папки расширения, добавив различные подразделы и значения в ключ CLSID расширения.

Некоторые из этих значений применяются только к расширениям с виртуальными точками соединения. Эти значения не применяются к расширениям, точки соединения которых являются папками файловой системы. Дополнительные сведения см. в разделе "Указание расположения расширения пространства имен". Чтобы изменить поведение расширения с виртуальной точкой соединения, добавьте одно или несколько следующих значений в ключ CLSID расширения:

  • WantsFORPARSING. Имя синтаксического анализа расширения с виртуальной точкой соединения обычно будет иметь форму ::{GUID}. Расширения этого типа обычно содержат виртуальные элементы. Однако некоторые расширения, такие как "Мои документы", фактически соответствуют папкам файловой системы, даже если они имеют виртуальные точки соединения. Если расширение представляет объекты файловой системы таким образом, можно задать значение WantsFORPARSING. Затем Обозреватель Windows запрашивает имя синтаксического анализа корневой папки, вызвав метод IShellFolder объекта папки::GetDisplayNameOf с параметром uFlags, равным SHGDN_FORPARSING и pidl, для одного пустого указателя на список идентификаторов элементов (PIDL). Пустой PIDL содержит только терминатор. Затем метод должен вернуть имя синтаксического анализа корневой папки ::{GUID}.
  • HideFolderVerbs. Команды, зарегистрированные в HKEY_CLASSES_ROOT \папке, обычно связаны со всеми расширениями. Они отображаются в контекстном меню расширения и могут вызываться ShellExecute. Чтобы предотвратить связь любой из этих команд с расширением, задайте значение HideFolderVerbs.
  • HideAsDelete. Если пользователь пытается удалить расширение, проводник Windows вместо этого скрывает расширение.
  • HideAsDeletePerUser. Это значение имеет тот же эффект, что и HideAsDelete, но на основе каждого пользователя. Расширение скрыто только для тех пользователей, которые пытались удалить его. Расширение отображается всем остальным пользователям.
  • QueryForOverlay. Задайте это значение, чтобы указать, что значок корневой папки может иметь наложение значка. Объект папки должен поддерживать интерфейс IShellIconOverlay. Перед отображением значка корневой папки проводник запросит значок наложения, вызвав один из двух методов 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 поместит знак плюса (+) рядом с значком папки.
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 назначает PIDL корневой папке и передает значение расширению во время инициализации. Затем расширение отвечает за назначение правильно созданного PIDL каждому из его объектов и предоставления этих ПИН-адресов проводнику Windows по запросу. Когда оболочка использует 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, приложение должно:

  1. Создайте структуру SHITEMID для каждого объекта.
  2. Соберите соответствующие структуры 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 является создание сохраняемой и переносимой структуры. В контексте ПИН-адресов смысл этих терминов:

  • Сохраняемая. Система часто помещает PID-адреса в различные типы долгосрочного хранилища, например ярлыки файлов. Затем он может восстановить эти ПИН-адреса из хранилища позже, возможно, после перезагрузки системы. PiDL, который был восстановлен из хранилища, должен по-прежнему быть допустимым и значимым для расширения. Это требование означает, например, что не следует использовать указатели или дескрипторы в структуре PIDL. PiDLs, содержащие этот тип данных, обычно будут бессмысленными, когда система позже восстанавливает их из хранилища.
  • Транспортабельный. PIDL должен оставаться значимым при переносе с одного компьютера на другой. Например, PIDL можно записать в ярлык-файл, скопировать его на диск floppy и перенести на другой компьютер. Этот 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. PiDLs можно создать для различных целей, но большинство задач используют один из двух типов PIDL. Самый простой, одноуровневый PIDL, идентифицирует объект относительно родительской папки. Этот тип PIDL используется многими методами IShellFolder . Одноуровневый PIDL содержит структуру SHITEMID объекта, за которой следует терминатор. Полный PIDL определяет путь через иерархию пространства имен от рабочего стола к объекту. Этот тип PIDL начинается на рабочем столе и содержит одну структуру SHITEMID для каждой папки в пути, а затем объект и терминатор. Полный PIDL однозначно идентифицирует объект в пределах всего пространства имен оболочки.

Самый простой способ создания PIDL — работать непосредственно с самой структурой ITEMIDLIST. Создайте структуру ITEMIDLIST, но выделите достаточно памяти для хранения всех структур SHITEMID. Адрес этой структуры будет указывать на начальную структуру SHITEMID . Определите значения для элементов этой начальной структуры, а затем добавьте столько дополнительных структур SHITEMID , сколько необходимо, в соответствующем порядке. В следующей процедуре описывается создание одноуровневого PIDL. Он содержит две структуры SHITEMID — структуру MYPIDLDATA , за которой следует терминатор:

  1. Используйте функцию CoTaskMemAlloc для выделения памяти для PIDL. Выделите достаточно памяти для частных данных, а также USHORT (два байта) для конца. Приведение результата к LPMYPIDLDATA.
  2. Задайте для элемента cb первой структуры MYPIDLDATA размер этой структуры. В этом примере можно задать cb sizeof(MYPIDLDATA). Если вы хотите использовать структуру переменной длины, необходимо вычислить значение cb.
  3. Назначьте соответствующие значения членам частных данных.
  4. Вычислите адрес следующей структуры SHITEMID . Приведение адреса текущей структуры MYPIDLDATA к LPBYTE и добавление этого значения в значение cb , определенное на шаге 3.
  5. В этом случае следующая структура SHITEMID является терминатором. Задайте для элемента cb-элемента структуры значение нулю.

Для более длинных ПИН-адресов выделите достаточно памяти и повторите шаги 3-5 для каждой дополнительной структуры SHITEMID.

Следующая пример функции принимает тип объекта и отображаемое имя и возвращает одноуровневый PIDL объекта. Функция предполагает, что отображаемое имя, включая его завершающий символ NULL , не превышает число символов, объявленных для структуры 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 базовых сведений о содержимом расширения. Эти интерфейсы, а также представление папок, являются все, что требуется для функционального расширения. Тем не менее, чтобы полностью использовать функции проводника Windows, большинство расширений также реализуют один или несколько необязательных интерфейсов.

Интерфейс IPersistFolder

Интерфейс IPersistFolder вызывается для инициализации нового объекта папки. Метод IPersistFolder::Initialize назначает полный PIDL новому объекту. Сохраните этот PIDL для дальнейшего использования. Например, объект папки должен использовать этот PIDL для создания полных ПИН-адресов для дочерних объектов. Создатель объекта папки также может вызвать IPersist::GetClassID для запроса CLSID объекта.

Как правило, объект папки создается и инициализируется методом IShellFolder::BindToObject. Однако, когда пользователь переходит в расширение, обозреватель Windows создает и инициализирует объект корневой папки расширения. PIDL, который получает объект корневой папки через IPersistFolder::Initialize , содержит путь от рабочего стола к корневой папке, которую потребуется создать полные PID-адреса для расширения.

Интерфейс IShellFolder

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

IShellFolder обычно является единственным интерфейсом папок, отличным от IPersistFolder, который напрямую предоставляется объектом папки. Хотя обозреватель Windows использует различные обязательные и необязательные интерфейсы для получения сведений о содержимом папки, он получает указатели на эти интерфейсы через IShellFolder.

Обозреватель Windows получает CLSID корневой папки расширения различными способами. Дополнительные сведения см. в разделе "Указание расположения расширения пространства имен" или отображения автономного представления расширения пространства имен. Затем обозреватель Windows использует этот CLSID для создания и инициализации экземпляра корневой папки и запроса интерфейса IShellFolder. Расширение создает объект папки для представления корневой папки и возвращает интерфейс IShellFolder объекта. Большая часть остальной части взаимодействия между расширением и проводником Windows происходит через IShellFolder. Обозреватель Windows вызывает IShellFolder :

  • Запрос объекта, который может перечислить содержимое корневой папки.
  • Получите различные типы сведений о содержимом корневой папки.
  • Запрос объекта, предоставляющего один из необязательных интерфейсов. Затем эти интерфейсы можно запрашивать для получения дополнительных сведений, таких как значки или контекстные меню.
  • Запрос объекта папки, представляющего вложенную папку корневой папки.

Когда пользователь открывает вложенную папку корневой папки, обозреватель Windows вызывает IShellFolder::BindToObject. Расширение создает и инициализирует новый объект папки для представления вложенной папки и возвращает его интерфейс IShellFolder. Затем обозреватель Windows вызывает этот интерфейс для различных типов сведений и т. д., пока пользователь не решит перейти в другое место в пространстве имен оболочки или закрыть проводник Windows.

Остальная часть этого раздела кратко описывает более важные методы IShellFolder и способы их реализации.

EnumObjects

Прежде чем отображать содержимое папки в представлении дерева, обозреватель Windows сначала должен определить, какая папка содержится, вызвав метод IShellFolder::EnumObjects. Этот метод создает стандартный объект перечисления OLE, который предоставляет интерфейс IEnumIDList и возвращает этот указатель интерфейса. Интерфейс IEnumIDList позволяет проводнику Windows получать PID-списки всех объектов, содержащихся в папке. Эти PID-адреса затем используются для получения сведений об объектах, содержащихся в папке. Дополнительные сведения см. в разделе "Интерфейс IEnumIDList".

Примечание.

Метод IEnumIDList::Next должен возвращать только PID-адреса, относящиеся к родительской папке. PIDL должен содержать только структуру SHITEMID объекта, за которой следует терминатор.

 

CreateViewObject

Перед отображением содержимого папки обозреватель Windows вызывает этот метод, чтобы запросить указатель на интерфейс IShellView. Этот интерфейс используется проводником Windows для управления представлением папок. Создайте объект представления папок и верните его интерфейс IShellView .

Метод IShellFolder::CreateViewObject также вызывается для запроса одного из необязательных интерфейсов, таких как IContextMenu, для самой папки. Реализация этого метода должна создать объект, предоставляющий запрошенный интерфейс и возвращающий указатель интерфейса. Если проводнику Windows требуется необязательный интерфейс для одного из объектов, содержащихся в папке, он вызовет IShellFolder::GetUIObjectOf.

GetUIObjectOf

Хотя основные сведения о содержимом папки доступны с помощью методов IShellFolder , расширение также может предоставить проводнику Windows различные виды дополнительных сведений. Например, можно указать значки содержимого папки или контекстного меню объекта. Обозреватель Windows вызывает метод IShellFolder::GetUIObjectOf , чтобы попытаться получить дополнительные сведения об объекте, который содержится в папке. Обозреватель Windows задает объект, для которого требуется информация, и iiD соответствующего интерфейса. Затем объект папки создает объект, предоставляющий запрошенный интерфейс и возвращающий указатель интерфейса.

Если расширение позволяет пользователям передавать объекты с помощью перетаскивания или буфера обмена, обозреватель Windows вызовет IShellFolder::GetUIObjectOf для запроса интерфейса IDataObject или IDropTarget. Дополнительные сведения см. в разделе "Передача объектов оболочки" с помощью перетаскивания и буфера обмена.

Обозреватель Windows вызывает IShellFolder::CreateViewObject , если он хочет такой же информации о самой папке.

BindToObject

Обозреватель Windows вызывает метод IShellFolder::BindToObject , когда пользователь пытается открыть одну из вложенных папок расширения. Если для riid задано значение IID_IShellFolder, необходимо создать и инициализировать объект папки, представляющий вложенную папку, и вернуть интерфейс IShellFolder объекта.

Примечание.

В настоящее время обозреватель Windows вызывает этот метод только для запроса интерфейса IShellFolder. Однако не предполагайте, что это всегда будет делом. Перед продолжением всегда следует проверить значение riid .

 

GetDisplayNameOf

Обозреватель Windows вызывает метод IShellFolder::GetDisplayNameOf для преобразования PIDL одного из объектов папки в имя. Этот PIDL должен быть относительным к родительской папке объекта. Другими словами, он должен содержать одну структуру SHITEMID, отличной от NULL. Так как существует несколько возможных способов именовать объекты, Обозреватель Windows указывает тип имени, задав один или несколько флагов SHGDNF в параметре uFlags . Одно из двух значений, SHGDN_NORMAL или SHGDN_INFOLDER, определяет, должно ли имя быть относительно папки или относительно рабочего стола. Можно задать одно из трех других значений, SHGDN_FOREDITING, SHGDN_FORADDRESSBAR или SHGDN_FORPARSING, чтобы указать, для чего будет использоваться имя.

Необходимо вернуть имя в виде структуры STRRET . Если SHGDN_FOREDITING, SHGDN_FORADDRESSBAR и SHGDN_FORPARSING не заданы, верните отображаемое имя объекта. Если установлен флаг SHGDN_FORPARSING, обозреватель Windows запрашивает имя синтаксического анализа. Имена синтаксического анализа передаются в IShellFolder::P arseDisplayName , чтобы получить PIDL объекта, даже если он может находиться под одной или несколькими уровнями под текущей папкой в иерархии пространства имен. Например, имя синтаксического анализа объекта файловой системы — это его путь. Полный путь любого объекта в файловой системе можно передать в метод IShellFolder рабочего стола ::P arseDisplayName , и он вернет полный piDL объекта.

Хотя имена синтаксического анализа являются текстовыми строками, они не обязательно должны включать отображаемое имя. При вызове IShellFolder::P arseDisplayName следует назначить имена синтаксического анализа на основе того, что будет работать наиболее эффективно. Например, многие из виртуальных папок Оболочки не являются частью файловой системы и не имеют полного пути. Вместо этого каждая папка назначается GUID, а имя синтаксического анализа принимает форму ::{GUID}. Независимо от того, какую схему вы используете, она должна быть в состоянии надежно "круговой путь". Например, если вызывающий объект передает имя синтаксического анализа в IShellFolder::P arseDisplayName, чтобы получить PIDL объекта, а затем передает piDL в IShellFolder::GetDisplayNameOf с набором флагов SHGDN_FORPARSING, вызывающий объект должен восстановить исходное имя синтаксического анализа.

GetAttributesOf

Обозреватель Windows вызывает метод IShellFolder::GetAttributesOf , чтобы определить атрибуты одного или нескольких элементов, содержащихся в объекте папки. Значение cidl дает количество элементов в запросе, а aPidl указывает на список их ПИН-адресов.

Так как тестирование для некоторых атрибутов может занять много времени, обозреватель Windows обычно ограничивает запрос подмножеством доступных флагов, задав их значения в rfgInOut. Метод должен протестировать только те атрибуты, флаги которых заданы в rfgInOut. Оставьте допустимые флаги заданными и очистите оставшуюся часть. Если в запрос входит несколько элементов, задайте только те флаги, которые применяются ко всем элементам.

Примечание.

Атрибуты должны быть правильно заданы для правильного отображения элемента. Например, если элемент является папкой, содержащей вложенные папки, необходимо задать флаг SFGAO_HASSUBFOLDER . В противном случае проводник Windows не отобразит значок элемента рядом с значком элемента в представлении дерева.

 

ParseDisplayName

Метод IShellFolder::P arseDisplayName представляет собой зеркальное изображение IShellFolder::GetDisplayNameOf. Чаще всего этот метод используется для преобразования имени синтаксического анализа объекта в связанный PIDL. Имя синтаксического анализа может ссылаться на любой объект, который находится под папкой в иерархии пространства имен. Возвращаемый PIDL относится к объекту папки, который предоставляет метод и обычно не является полным. Другими словами, хотя PIDL может содержать несколько структур SHITEMID , первое будет либо самим объектом, либо первым вложенным папкой в пути из папки в объект. Вызывающий объект должен добавить этот PIDL в полный piDL папки, чтобы получить полный PIDL для объекта.

IShellFolder::P arseDisplayName также можно вызвать для запроса атрибутов объекта. Так как определение всех применимых атрибутов может занять много времени, вызывающий будет задавать только те флаги SFGAO_XXX , которые представляют сведения, интересующие вызывающего объекта. Необходимо определить, какие из этих атрибутов соответствуют объекту, и очистить оставшиеся флаги.

Интерфейс IEnumIDList

Если проводнику Windows нужно перечислить объекты, содержащиеся в папке, он вызывает IShellFolder::EnumObjects. Объект папки должен создать объект перечисления, предоставляющий интерфейс IEnumIDList и возвращающий этот указатель интерфейса. Затем проводник Windows будет использовать IEnumIDList для перечисления PID-адресов всех объектов, содержащихся в папке.

IEnumIDList — это стандартный интерфейс перечисления OLE и реализуется обычным образом. Помните, однако, что возвращаемые ИДЕНТИФИКАТОРЫ должны быть относительными к папке и содержать только структуру SHITEMID объекта и терминатор.

Реализация необязательных интерфейсов

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

Ни один из необязательных интерфейсов не предоставляется непосредственно объектом папки. Вместо этого обозреватель Windows вызывает один из двух методов IShellFolder для запроса интерфейса:

  • Обозреватель Windows вызывает объект папки IShellFolder::GetUIObjectOf , чтобы запросить интерфейс для одного из объектов, содержащихся в папке.
  • Обозреватель Windows вызывает объект папки IShellFolder::CreateViewObject , чтобы запросить интерфейс для самой папки.

Чтобы предоставить сведения, объект папки создает объект, предоставляющий запрошенный интерфейс и возвращающий указатель интерфейса. Затем обозреватель Windows вызывает этот интерфейс для получения необходимых сведений. В этом разделе рассматриваются наиболее часто используемые необязательные интерфейсы.

IExtractIcon

Обозреватель Windows запрашивает интерфейс IExtractIcon перед отображением содержимого папки. Интерфейс позволяет расширению указывать пользовательские значки для объектов, содержащихся в папке. В противном случае будут использоваться стандартные значки файлов и папок. Чтобы предоставить пользовательский значок, создайте объект извлечения значков , который предоставляет IExtractIcon и возвращает указатель на этот интерфейс. Дополнительные сведения см. в справочной документации по IExtractIcon или создании обработчиков значков.

IContextMenu

Когда пользователь щелкает объект правой кнопкой мыши, обозреватель Windows запрашивает интерфейс IContextMenu . Чтобы предоставить контекстные меню для объектов, создайте объект обработчика меню и верните его интерфейс IContextMenu .

Процедуры создания объекта обработчика меню очень похожи на те, которые используются для создания расширения оболочки обработчика меню. Дополнительные сведения см. в разделе "Создание обработчиков контекстного меню" или справочника по IContextMenu2, IContextMenu2 или IContextMenu3.

IQueryInfo

Обозреватель Windows вызывает интерфейс IQueryInfo для получения текстовой строки infotip.

IDataObject и IDropTarget

Когда объекты отображаются в проводнике Windows, объект папки не имеет прямого способа узнать, когда пользователь пытается вырезать, копировать или перетаскивать объект. Вместо этого обозреватель Windows запрашивает интерфейс IDataObject . Чтобы разрешить перенос объекта, создайте объект данных и верните указатель на его интерфейс IDataObject .

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

Обработка передачи данных является одним из более сложных аспектов написания расширений пространства имен. Подробные сведения см. в разделе "Передача объектов оболочки" с помощью перетаскивания и буфера обмена.

Работа с реализацией представления папок оболочки по умолчанию

Источники данных, использующие объект представления папок оболочки по умолчанию (DefView), должны реализовать следующие интерфейсы:

При необходимости они также могут реализовать IPersistFolder3.