- •Методические указания для выполнения лабораторной работы №2.6 по курсу «Операционные системы и системное программирование»
- •Цель работы
- •Теоретические сведения
- •Пример 1 «Добавление пунктов в контекстное меню для отдельных расширений файлов»
- •Использование AppWizard.
- •Интерфейс инициализации
- •Интерфейс взаимодействия с контекстным меню
- •Модификация контекстного меню
- •Отображение подсказки в строке состояния
- •Выполнение выбора пользователя
- •Регистрация расширения оболочки
- •Отладка расширения оболочки
- •Результат
- •Пример 2 «Добавление пунктов в контекстное меню для всех файлов не зависимо от расширения»
- •Дополнительные функции расширения, добавляющего пункты к контекстному меню оболочки.
- •Использование AppWizard
- •Интерфейс инициализации
- •Добавление пунктов к меню
- •Подсказка в строке состояния и "действие"
- •Выполнение выбора пользователя
- •Регистрация расширения
- •Результат
- •Другие способы регистрации расширения
- •Пример 3 «Использование разделяемой с оболочкой памяти»
- •Расширение QueryInfo
- •Использование AppWizard
- •Интерфейс инициализации
- •Создание текста для тултипа
- •Регистрация расширения оболочки
- •Пример 4 «Обработчик перетаскивания контекстного меню»
- •Обработчик перетаскивания
- •Интерфейс инициализации
- •Модификация контекстного меню
- •Создание связи
- •Обеспечение подсказки в строке состояния
- •Создание связи
- •Регистрация расширения
- •Пример 5 «Добавления новых страниц в набор свойств файлов»
- •Обработчик набора свойств
- •Использование AppWizard
- •Интерфейс инициализации
- •Добавление страниц свойств
- •Неприятная ситуация с периодом жизни объектов
- •Функции обратного вызова страницы свойств
- •Обработчики сообщений страницы свойств
- •Регистрация расширения
- •Пример 6 «Обработчик сбрасывания в меню Send To»
- •Обработчик сбрасывания
- •Использование AppWizard
- •Интерфейс инициализации
- •Участвуем в операции drag and drop
- •DragEnter()
- •DragLeave()
- •Регистрация расширения
- •Пример 7 «Owner-drawn меню в расширениях контекстных меню и по созданию расширения контекстного меню, которое отзывается на правый щелчок на фоне окна каталога» Расширение 1 - Пункты меню owner-drawn.
- •Использование AppWizard
- •Интерфейс инициализации.
- •Взаимодействие с контекстным меню
- •Модифицирование контекстного меню.
- •Отображение всплывающей подсказки в строке состояния.
- •Выполнение выбора пользователя.
- •Рисование пункта меню.
- •Обработка wm_measureitem
- •Обработка wm_drawitem
- •Регистрация расширения оболочки
- •Расширение 2 - Обработка щелчка правой кнопкой мыши на фоне окна каталога.
- •Отличия в iShellExtInit::Initialize()
- •Отличия в регистрации.
- •Пример 8 «Добавление колонки в окно детального просмотра Проводника» Детальный просмотр в Windows 2000
- •Использование AppWizard
- •Интерфейс расширения
- •Инициализация
- •Перечисление новых столбцов
- •Отображение данных в столбцах
- •Небольшое отступление - обработка тэгов id3
- •Как это все выглядит?
- •Регистрация расширения оболочки
- •Еще одна полезная штучка - InfoTips
- •Пример 9 «Настройка иконок, отображаемых для файлов заданного типа» Файловые иконки в Проводнике
- •Использование AppWizard
- •Интерфейс расширения
- •Интерфейс инициализации
- •Интерфейс iExtractIcon
- •Извлечение методом 1
- •Извлечение методом 2
- •Регистрация расширения
- •Пример 10 «Расширение оболочки для изменения иконок у dll в зависимости от их типа»
- •Как установить
- •Подробности реализации
- •Задания для лабораторных работ
- •Содержание отчета
Интерфейс расширения
Хэндлер иконок реализует два интерфейса, 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) иконок для использования Проводником.
