- •Методические указания для выполнения лабораторной работы №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 в зависимости от их типа»
- •Как установить
- •Подробности реализации
- •Задания для лабораторных работ
- •Содержание отчета
Пример 3 «Использование разделяемой с оболочкой памяти»
В этом примере рассмотрим другой тип расширений - использование памяти, разделяемую с оболочкой и как использовать MFC вместе с ATL.
Расширение QueryInfo
Active Desktop имеет одну новую особенность - когда вы перемещаете указатель мыши над объектом, появляется всплывающая подсказка - тултип, описывающая этот объект. Например, перемещение мыши над объектом "Мой компьютер" вызовет появление тултипа:
Другие объекты, такие как "Сетевое окружение" и "Панель управления", имеют аналогичные тултипы. Используя расширение QueryInfo мы можем внести свою собственную информацию в строку описания для объектов оболочки.
Замечание по поводу имени расширения - "QueryInfo". Это название придумано мною. Я так назвал расширение после применения интерфейса IQueryInfo. Это не официальное название. Я смотрел MSDN за октябрь 1999 года и не смог найти даже ссылку на этот тип расширений. Однако это расширение определенно предусмотрено, так как Microsoft Office использует их для своих типов файлов:
WinZip версии 8 также использует расширение QueryInfo для сжатых файлов:
Самая лучшая документация, которую я нашел - это статья Dino Esposito "Enhance Your User's Experience with New Infotip and Icon Overlay Shell Extensions" в журнале MSDN за март 2000 года.
В примере 3 расширение реализует быстрый просмотр текстовых файлов. Оно будет отображать в тултипе первую строку файла и его размер. Информация будет появляться во время перемещения курсора над TXT-файлами.
Использование AppWizard
Запустите AppWizard и создайте новый ATL COM проект. Назовем его TxtInfo. Поскольку в этот раз мы собираемся использовать MFC, нужно проверить переключатель Support MFC, он должен быть включен. Затем щелкните Finish. Чтобы добавить COM объект к DLL, перейдите в дерево просмотра классов, ClassView, щелкните правой кнопкой на пункте TxtInfo classes и укажите New ATL Object.
В мастере ATL объектов, на первой панели уже указан Simple Object, поэтому просто щелкните Next. Во второй панели, в поле редактирования Short Name введите краткое имя TxtInfoShlExt и щелкните OK. (Остальные поля заполняются автоматически.) Мы создали класс CTxtInfoShlExt, который содержит основной код для реализации объекта COM. Добавим свой код к этому классу.
Если вы внимательно посмотрите на дерево ClassView, то увидите, что появился новый класс, CTxtInfoApp, производный от CWinApp. Присутствие этого класса и глобальной переменной theApp делает библиотеку MFC доступной для нас, как будто мы пишем нормальную MFC DLL.
Интерфейс инициализации
Раньше, для предыдущих расширений, мы реализовывали интерфейс IShellExtInit, чтобы проводник мог инициализировать наши объекты. Для некоторых объектов оболочки используется другой инициализационный интерфейс - IPersistFile, и QueryInfo - одно из них. Чем отличаются эти интерфейсы? Если вы помните, IShellExtInit::Initialize() получает указатель на IDataObject, с помощью которого можно перечислить все выбранные файлы. IPersistFile используется для тех расширений, которые оперируют только одним файлом. Так как курсор в определенный момент времени может находиться только в области одного объекта, QueryInfo использует для инициализации IPersistFile.
Первым делом добавим IPersistFile в список интерфейсов, которые реализуются CTxtInfoShlExt. Откройте файл TxtInfoShlExt.h и добавьте выделенные строки:
|
#include <comdef.h> #include <shlobj.h>
class ATL_NO_VTABLE CTxtInfoShlExt : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CTxtInfoShlExt, &CLSID_TxtInfoShlExt>, public IDispatchImpl<ITxtInfoShlExt, &IID_ITxtInfoShlExt, &LIBID_TXTINFOLib>, public IPersistFile { BEGIN_COM_MAP(CTxtInfoShlExt) COM_INTERFACE_ENTRY(ITxtInfoShlExt) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IPersistFile) END_COM_MAP() |
Нам также понадобится переменная для сохранения имени файла, которое передаст нам проводник:
|
protected: // ITxtInfoShlExt CString m_sFilename; |
Обратите внимание, что мы можем использовать объекты MFC везде, где нам захочется.
В документации на IPersistFile описано много методов, но к счастью нам достаточно реализовать только Load(). Вот прототипы методов IPersistFile:
|
public: // IPersistFile STDMETHOD(GetClassID)(LPCLSID) { return E_NOTIMPL; } STDMETHOD(IsDirty)() { return E_NOTIMPL; } STDMETHOD(Load)(LPCOLESTR, DWORD); STDMETHOD(Save)(LPCOLESTR, BOOL) { return E_NOTIMPL; } STDMETHOD(SaveCompleted)(LPCOLESTR) { return E_NOTIMPL; } STDMETHOD(GetCurFile)(LPOLESTR*) { return E_NOTIMPL; } |
Все методы, кроме Load() возвращают E_NOTIMPL в знак того, что они не реализованы.
Скрашивает ситуацию также то, что в действительности метод Load() очень прост. Он сохраняет имя файла, переданное ему проводником. Это как раз тот файл, в области которого находится курсор.
|
HRESULT CTxtInfoShlExt::Load ( LPCOLESTR wszFilename, DWORD dwMode ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // init MFC
// Let CString convert the filename to ANSI if necessary. m_sFilename = wszFilename;
return S_OK; } |
Первая строка в начале функции необходима для корректной работы DLL. Поскольку наша DLL будет загружена не-MFC приложением, каждая экспортируемая функция, использующая MFC, должна инициализировать MFC вручную. Если вы не включите эту строку, многие MFC-функции (в основном функции, работающие с ресурсами) прекратят свою работу.
Имя файла сохраняется в m_sFilename для дальнейшего использования. Заметьте, какие я имею преимущества с оператором присваивания CString по конвертированию строки в ANSI, если DLL собирается как ANSI.
