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


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

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

Все обработчики расширений оболочки являются объектами объектной модели компонента (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.

Сначала оболочка вызывает 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;
}

Настройка infotip

Существует два способа настройки подсказок. Одним из способов является реализация объекта, который поддерживает 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}, pid, где имя_атрибута является каноническим именем свойства и {fmtid}, pid является парой FMTID/PID.

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

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

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

 

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