Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП - методички / OS&SP_Lab_2.6(shell).doc
Скачиваний:
95
Добавлен:
18.05.2015
Размер:
1.12 Mб
Скачать

Интерфейс расширения

Хэндлер иконок реализует два интерфейса, IPersistFile и IExtractIcon. Вспомните, что IPersistFile используется, чтобы инициализировать расширения, которые оперируют одиночными файлами, в отличии от IShellExtInit, который предназначен для расширений, действующих на всех отмеченных файлах сразу. IExtractIcon имеет два метода, оба они используются для информирования Проводника о том, какую иконку использовать для данного файла.

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

Интерфейс инициализации

Чтобы добавить поддержку IPersistFile к нашему COM объекту, откройте TxtIconShlExt.h и добавьте выделенные строки:

#include <comdef.h>

#include <shlobj.h>

#include <atlconv.h>

/////////////////////////////////////////////////////////////////////////////

// CTxtIconShlExt

class ATL_NO_VTABLE CTxtIconShlExt :

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CTxtIconShlExt, &CLSID_TxtIconShlExt>,

public IDispatchImpl<ITxtIconShlExt, &IID_ITxtIconShlExt, &LIBID_TXTFILEICONSLib>,

public IPersistFile

{

BEGIN_COM_MAP(CTxtIconShlExt)

COM_INTERFACE_ENTRY(ITxtIconShlExt)

COM_INTERFACE_ENTRY(IDispatch)

COM_INTERFACE_ENTRY(IPersistFile)

END_COM_MAP()

public:

// IPersistFile

STDMETHOD(GetClassID)( CLSID* ) { return E_NOTIMPL; }

STDMETHOD(IsDirty)() { return E_NOTIMPL; }

STDMETHOD(Save)( LPCOLESTR, BOOL ) { return E_NOTIMPL; }

STDMETHOD(SaveCompleted)( LPCOLESTR ) { return E_NOTIMPL; }

STDMETHOD(GetCurFile)( LPOLESTR* ) { return E_NOTIMPL; }

STDMETHOD(Load)( LPCOLESTR wszFile, DWORD /*dwMode*/ )

{

USES_CONVERSION;

lstrcpyn ( m_szFilename, OLE2CT(wszFile), MAX_PATH );

return S_OK;

}

protected:

TCHAR m_szFilename [MAX_PATH]; // Полный путь к рассматриваемому файлу

DWORDLONG m_ldwFileSize; // Размер файла; Используется при извлечении методом 2.

};

Как и в других расширениях, которые используют IPersistFile, только один метод нуждается в реализации - Load(), поскольку с помощью него Проводник сообщает нам, с каким файлом мы работаем. Реализация Load() сделана inline, это просто копирование имени файла в переменную m_szFilename для дальнейшего использования.

Интерфейс iExtractIcon

Хэндлер иконок также реализует интерфейс IExtractIcon, который Проводник вызывает, когда ему нужна иконка для файла. Поскольку наше расширение предназначено для текстовых файлов, Проводник вызывает IExtractIcon как только текстовый файл появится в его окне или меню "Start" ("Пуск"). Чтобы добавить IExtractIcon к нашему COM объекту откройте TxtIconShlExt.h и добавьте выделенные строки:

/////////////////////////////////////////////////////////////////////////////

// CTxtIconShlExt

class ATL_NO_VTABLE CTxtIconShlExt :

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CTxtIconShlExt, &CLSID_TxtIconShlExt>,

public IDispatchImpl<ITxtIconShlExt, &IID_ITxtIconShlExt, &LIBID_TXTFILEICONSLib>,

public IPersistFile,

public IExtractIcon

{

BEGIN_COM_MAP(CTxtIconShlExt)

COM_INTERFACE_ENTRY(ITxtIconShlExt)

COM_INTERFACE_ENTRY(IDispatch)

COM_INTERFACE_ENTRY(IPersistFile)

COM_INTERFACE_ENTRY(IExtractIcon)

END_COM_MAP()

public:

// IExtractIcon

STDMETHOD(GetIconLocation)( UINT uFlags, LPTSTR szIconFile, UINT cchMax,

int* piIndex, UINT* pwFlags );

STDMETHOD(Extract)( LPCTSTR pszFile, UINT nIconIndex, HICON* phiconLarge,

HICON* phiconSmall, UINT nIconSize );

};

Есть два способа передать иконку Проводнику. Во-первых, GetIconLocation() может вернуть пару имя_файла/индекс, которая состоит из имени файла содержащего иконку и начинающегося с 0 индекса иконки в этом файле. Например, C:\windows\system\shell32.dll/9 одно из возможных значений, которое говорит Проводнику использовать иконку #9 (считая с 0) из shell32.dll. Это не означает использовать иконку чей идентификатор ресурса равен 9, это означает просмотреть идентификаторы ресурсов иконок по порядку (от меньшего к большему) и использовать девятый. Метод Extract() при этом ничего не делает, кроме возврата S_FALSE, чтобы сообщить Проводнику, что ему самому нужно извлечь иконку.

Особенностью этого метода является то, что Проводник может вызвать, а может и не вызывать Extract() после вызова GetIconLocation(). У Проводника есть кэш иконок, в котором хранятся недавно использованные исконки. Если GetIconLocation() передает пару - имя файла/индекс, которая недавно использовалась и иконка все еще в кэше, Проводник извлечет иконку от туда и не будет вызывать Extract() поскольку в этом нет необходимости.

Второй метод заключается в том, чтобы вернуть из GetIconLocation() флаг "не смотреть в кэш", заставляющий Проводник всегда вызывать Extract(). Далее уже Extract() отвечает за загрузку иконки и возврат дескрипторов (HICON) большой (32х32) и малой (16х16) иконок для использования Проводником.

Соседние файлы в папке ОСиСП - методички