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


Инициализация обработчиков расширений оболочки

Большая часть реализации объекта обработчика расширения оболочки определяется его типом. Однако существуют некоторые общие элементы. В этом разделе рассматриваются те аспекты реализации, которые совместно используются всеми обработчиками расширений оболочки.

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

  • DllMain. Стандартная точка входа в библиотеку DLL.
  • DllGetClassObject. Предоставляет фабрику классов объекта.
  • DllCanUnloadNow. COM вызывает эту функцию, чтобы определить, обслуживает ли объект какие-либо клиенты. В противном случае система может выгрузить библиотеку DLL и освободить связанную память.

Как и все COM-объекты, обработчики расширений оболочки должны реализовывать интерфейс IUnknown и фабрику классов. Большинство из них также должны реализовывать интерфейс IPersistFile или IShellExtInit в Windows XP или более ранней версии. Они были заменены IInitializeWithStream, IInitializeWithItem и IInitializeWithFile в Windows Vista. Оболочка использует эти интерфейсы для инициализации обработчика.

Интерфейс IPersistFile должен быть реализован следующим образом:

  • Обработчики значков
  • Обработчики данных
  • Удаление обработчиков

Интерфейс IShellExtInit должен быть реализован следующим образом:

  • Обработчики контекстного меню
  • Обработчики перетаскивания
  • Обработчики страниц свойств

В оставшейся части этой статьи рассматриваются следующие темы:

Реализация IPersistFile

Интерфейс IPersistFile предназначен для загрузки или сохранения объекта из файла диска. В ней есть шесть методов, помимо IUnknown, пять собственных, и метод GetClassID , который он наследует от IPersist. При использовании расширений оболочки IPersist используется только для инициализации объекта обработчика расширения оболочки. Так как обычно нет необходимости считывать данные с диска или записывать его на диск, только для методов GetClassID и Load требуется реализация nontoken.

Оболочка сначала вызывает GetClassID , а функция возвращает идентификатор класса (CLSID) объекта обработчика расширения. Затем оболочка вызывает load и передает два значения. Первый, pszFile, — это строка Юникода с именем файла или папки, с которыми будет работать оболочка. Второй — dwMode, который указывает режим доступа к файлам. Так как обычно нет необходимости в доступе к файлам, dwMode обычно равен нулю. Метод сохраняет эти значения по мере необходимости для последующей ссылки.

В следующем фрагменте кода показано, как типичный обработчик расширения оболочки реализует методы GetClassID и Load . Он предназначен для обработки ANSI или Юникода. CLSID_SampleExtHandler — GUID объекта обработчика расширений, а CSampleShellExtension — имя класса, используемого для реализации интерфейса. Переменные m_szFileName и m_dwMode являются частными переменными, которые используются для хранения имени файла и флагов доступа.

class CSampleShellExtension : public IPersistFile
{
    // Method declarations not included

    private:
    WCHAR m_szFileName[MAX_PATH];    // The file name
    DWORD m_dwMode;                  // The file access mode
}

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
    *pCLSID = CLSID_SampleExtHandler;
}

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
    m_dwMode = dwMode;
    return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile); 
}

// The implementation sample is continued in the next section.

Реализация IShellExtInit

Интерфейс IShellExtInit содержит только один метод , IShellExtInit::Initialize, помимо IUnknown. Метод имеет три параметра, которые оболочка может использовать для передачи различных типов информации. Передаваемые значения зависят от типа обработчика, а для некоторых можно задать значение NULL.

  • pidlFolder содержит указатель папки на список идентификаторов элементов (PIDL). Это абсолютный PIDL. Для расширений страниц свойств это значение равно NULL. Для расширений контекстного меню это PIDL папки, содержащей элемент, контекстное меню которого отображается. Для обработчиков перетаскивания без определенных значений это PIDL целевой папки.
  • pDataObject содержит указатель на интерфейс IDataObject объекта данных. Объект данных содержит одно или несколько имен файлов в CF_HDROP формате.
  • hRegKey содержит раздел реестра для типа файлового объекта или папки.

Метод IShellExtInit::Initialize сохраняет имя файла, указатель IDataObject и раздел реестра для последующего использования. В следующем фрагменте кода показана реализация IShellExtInit::Initialize. Для простоты в этом примере предполагается, что объект данных содержит только один файл. Как правило, объект данных может содержать несколько файлов, каждый из которых необходимо извлечь.

// This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.

class CSampleShellExtension : public IShellExtInit
{
    // Method declarations not included
    
    private:
    // IDList of the folder for extensions invoked on the folder, such as 
    // background context menu handlers or nondefault drag-and-drop handlers. 
    PIDLIST_ABSOLUTE m_pidlFolder;
    
    // The data object contains an expression of the items that the handler is 
    // being initialized for. Use SHCreateShellItemArrayFromDataObject to 
    // convert this object to an array of items. Use SHGetItemFromObject if you
    // are only interested in a single Shell item. If you need a file system
    // path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
    IDataObject *m_pdtobj;
    
    // For context menu handlers, the registry key provides access to verb 
    // instance data that might be stored there. This is a rare feature to use 
    // so most extensions do not need this variable.
    HKEY m_hRegKey;             
}
    
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.

IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder,
                                                 __in_opt IDataObject *pDataObject, 
                                                 __in_opt HKEY hRegKey) 
{ 
    // In some cases, handlers are initialized multiple times. Therefore, 
    // clear any previous state here.
    CoTaskMemFree(m_pidlFolder);
    m_pidlFolder = NULL;
    
    if (m_pdtobj)
    { 
        m_pdtobj->Release(); 
    }
    
    if (m_hRegKey)
    {
        RegCloseKey(m_hRegKey);
        m_hRegKey = NULL;
    }
    
    // Capture the inputs for use later.
    HRESULT hr = S_OK;
    
    if (pidlFolder)
    {
        m_pidlFolder = ILClone(pidlFolder);   // Make a copy to use later.
        hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
    }
    
    if (SUCCEEDED(hr))
    {
        // If a data object pointer was passed into the method, save it and
        // extract the file name. 
        if (pDataObject) 
        { 
            m_pdtobj = pDataObject; 
            m_pdtobj->AddRef(); 
        }
    
        // It is uncommon to use the registry handle, but if you need it,
        // duplicate it now.
        if (hRegKey)
        {
            LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey); 
            hr = HRESULT_FROM_WIN32(result);
        }
    }
    
    return hr;
}

Настройка подсказки

Существует два способа настройки подсказок. Один из способов — реализовать объект, поддерживающий IQueryInfo , а затем зарегистрировать объект в соответствующем подразделе в реестре (см. ниже). Кроме того, можно указать фиксированную строку или список определенных свойств файла, которые будут отображаться.

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

HKEY_CLASSES_ROOT
   CLSID
      {CLSID}
         InfoTip = InfoTip string for your namespace extension

Чтобы отобразить фиксированную строку для типа файла, создайте подраздел InfoTip под ключом ProgID типа файла, для которого требуется предоставить подсказки. Задайте для данных этого подраздела строку, которую вы хотите отобразить.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = InfoTip string for all files of this type

Если вы хотите, чтобы оболочка отображала определенные свойства файла в подсказке для определенного типа файла, создайте подраздел InfoTip под ключом ProgID этого типа файла. Задайте данные этого подраздела как разделенный точкой с запятой список имен канонических свойств или пары "{fmtid}", где propname является каноническим именем свойства, а {fmtid},pidпара FMTID/PID.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = propname;propname;{fmtid},pid;{fmtid},pid

Можно использовать следующие имена свойств.

Имя свойства Описание Получено из
Автор Автор документа PIDSI_AUTHOR
Заголовок Название документа PIDSI_TITLE
Тема Сводка по теме PIDSI_SUBJECT
Комментировать Комментарии к документу свойства PIDSI_COMMENT или папки или диска
PageCount Количество страниц PIDSI_PAGECOUNT
Имя Понятное имя Стандартное представление папок
OriginalLocation Расположение исходного файла Папка «Портфель» и «Корзина»
DateDeleted Дата удаления файла Папка корзины
Тип Тип файла Стандартное представление сведений о папке
Размер Размер файла Стандартное представление сведений о папке
SyncCopyIn То же, что и OriginalLocation То же, что и OriginalLocation
Изменен Дата последнего изменения Стандартное представление сведений о папке
Создание Дата создания Стандартное представление сведений о папке
Осуществляемый доступ Дата последнего доступа Стандартное представление сведений о папке
InFolder Каталог, содержащий файл Результаты поиска документов
Ранг Качество поиска соответствия Результаты поиска документов
FreeSpace Доступное дисковое пространство Диски
NumberOfVisits Количество посещений Папка "Избранное"
Атрибуты Атрибуты файла Стандартное представление сведений о папке
Company Название организации PIDDSI_COMPANY
Категория Категория документа PIDDSI_CATEGORY
Авторские права Авторские права на сми PIDMSI_COPYRIGHT
HTMLInfoTipFile HTML InfoTip-файл файл Desktop.ini для папки

 

Регистрация обработчиков расширений оболочки