- •Методические указания для выполнения лабораторной работы №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 в зависимости от их типа»
- •Как установить
- •Подробности реализации
- •Задания для лабораторных работ
- •Содержание отчета
Добавление пунктов к меню
Следующий этап - методы IContextMenu. Как и раньше, необходимо добавить IContextMenu к списку интерфейсов, реализуемых CDllRegShlExt. Действия, сопровождающие эту операцию описаны в первой части.
Вот как будут выглядеть пункты, которые мы добавим к контекстному меню. Однин для регистрации файлов, другой - для из разрегистрации.
Начало реализации QueryContextMenu() аналогично описанному в первой части. Мы проверяем uFlags и немедленно делаем возврат, если обнаружим флаг CMF_DEFAULTONLY.
|
HRESULT CDLLRegShlExt::QueryContextMenu ( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags ) { UINT uCmdID = uidFirstCmd;
// If the flags include CMF_DEFAULTONLY then we shouldn't do anything. if ( uFlags & CMF_DEFAULTONLY ) { return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 ); } |
Затем мы добавляем пункт меню "Register servers". Далее кое-что новенькое. Мы установим картинку для этого пункта. Таким образом, перед нашим пунктом меню будет появляться пиктограмма, также как это делает WinZip.
|
// Add our register/unregister items. InsertMenu ( hmenu, uMenuIndex, MF_STRING | MF_BYPOSITION, uCmdID++, _T("Register server(s)") );
// Set the bitmap for the register item. if ( NULL != m_hRegBmp ) { SetMenuItemBitmaps ( hmenu, uMenuIndex, MF_BYPOSITION, m_hRegBmp, NULL ); }
uMenuIndex++; |
Функция API SetMenuItemBitmaps() приводит в действие механизм отображения картинки перед пунктом меню "Register servers". Заметьте, что uCmdID инкрементируется для следующего вызова InsertMenu(). И в конце этого шага также наращивается uMenuIndex, так что второй пункт меню появится вслед за первым.
Далее следует добавление второго пункта меню. Код реализации идентичен коду для первого пункта.
|
InsertMenu ( hmenu, uMenuIndex, MF_STRING | MF_BYPOSITION, uCmdID++, _T("Unregister server(s)") );
// Set the bitmap for the unregister item. if ( NULL != m_hUnregBmp ) { SetMenuItemBitmaps ( hmenu, uMenuIndex, MF_BYPOSITION, m_hUnregBmp, NULL ); } |
В конце мы сообщаем проводнику, сколько пунктов меню мы добавили:
|
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 2 ); |
Подсказка в строке состояния и "действие"
Для отображения подсказки и извлечения "действия" из добавленных команд проводнику потребуется вызвать метод GetCommandString(). Создаваемое нами расширение отличается тем, что добавляет два пункта к меню. Поэтому, чтобы определить какой из пунктов меню был выделен, нам потребуется исследовать параметр uCmdID:
|
#include <atlconv.h>
HRESULT CDLLRegShlExt::GetCommandString ( UINT uCmdID, UINT uFlags, UINT* puReserved, LPSTR szName, UINT cchMax ) { LPCTSTR szPrompt;
USES_CONVERSION;
if ( uFlags & GCS_HELPTEXT ) { switch ( uCmdID ) { case 0: szPrompt = _T("Register all selected COM servers"); break;
case 1: szPrompt = _T("Unregister all selected COM servers"); break;
default: return E_INVALIDARG; break; } |
Если uCmdID равен 0, то выделен первый пункт (регистрация), если 1, то второй (разрегистрация). После этого мы определяем строку подсказки, копируем ее в установленный буфер, конвертируя в UNICODE, если это необходимо.
|
// Copy the help text into the supplied buffer. If the shell wants // a Unicode string, we need to case szName to an LPCWSTR.
if ( uFlags & GCS_UNICODE ) { lstrcpynW ( (LPWSTR) szName, T2CW(szPrompt), cchMax ); } else { lstrcpynA ( szName, T2CA(szPrompt), cchMax ); } } |
Я также написал для этого расширения код, который извлекает "действие". Однако, при тестировании на Windows 98 проводник никогда не пытался вызвать GetCommandString(), чтобы извлечь "действие". Я даже написал пробную программу, которая вызывала ShellExecute() для DLL и пыталась использовать "действие". Но ничего не работало. Я не знаю, отличается ли чем-то поведение в Windows NT. По этой причине я опустил реализацию кода извлечения "действия", но вы можете попробовать реализовать его самостоятельно, если вам интересно.
