- •Методические указания для выполнения лабораторной работы №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 в зависимости от их типа»
- •Как установить
- •Подробности реализации
- •Задания для лабораторных работ
- •Содержание отчета
Отображение всплывающей подсказки в строке состояния.
Отображение всплывающей подсказки ничем не отличается от аналогичной операции в предыдущих расширениях. Проводник вызывает GetCommandString(), чтобы извлечь строку, которую он покажет в строке состояния.
|
#include <atlconv.h> // for ATL string conversion macros
STDMETHODIMP CBmpCtxMenuExt::GetCommandString ( UINT uCmd, UINT uFlags, UINT* puReserved, LPSTR pszName, UINT cchMax ) { static LPCTSTR szHelpString = _T("Select this thumbnail to view the entire picture.");
USES_CONVERSION;
// Check idCmd, it must be 0 since we have only one menu item. if ( 0 != uCmd ) return E_INVALIDARG;
// If Explorer is asking for a help string, copy our string into the // supplied buffer. if ( uFlags & GCS_HELPTEXT ) { if ( uFlags & GCS_UNICODE ) { // We need to cast pszName to a Unicode string, and then use the // Unicode string copy API. lstrcpynW ( (LPWSTR) pszName, T2CW(szHelpString), cchMax ); } else { // Use the ANSI string copy API to return the help string. lstrcpynA ( pszName, T2CA(szHelpString), cchMax ); } }
return S_OK; } |
Выполнение выбора пользователя.
Последний метод в IContextMenu - это InvokeCommand(). Этот метод будет вызван, если пользователь щелкнет на пункте меню, добавленном нами. Расширение вызовет ShellExecute(), чтобы открыть картинку в Paint (или другой программе, ассоциированной с BMP-файлами).
|
STDMETHODIMP CBmpCtxMenuExt::InvokeCommand ( LPCMINVOKECOMMANDINFO pInfo ) { // If lpVerb really points to a string, ignore this function call and bail out. if ( 0 != HIWORD( pInfo->lpVerb )) return E_INVALIDARG;
// The command ID must be 0 since we only have one menu item. if ( 0 != LOWORD( pInfo->lpVerb )) return E_INVALIDARG;
// Open the bitmap in the default paint program. ShellExecute ( pInfo->hwnd, _T("open"), m_szFile, NULL, NULL, SW_SHOWNORMAL );
return S_OK; } |
Рисование пункта меню.
Итак, держу пари, вы заскучали к этому времени со всеми этими кодами, которые вы видели и раньше. Пора приступить к новым и интересным штучкам! Два дополнительных метода IContextMenu2 и IContextMenu3 приведены ниже. Они просто вызывают единственную вспомогательную функцию, которая, в свою очередь, вызывает обработчик сообщений. Я разработал этот метод чтобы избежать двух разных версий обработчиков сообщений (по одному для IContextMenu2 и IContextMenu3). В HandleMenuMsg2() есть одна странность, связанная с параметром LRESULT, которую я объясню в комментариях.
|
STDMETHODIMP CBmpCtxMenuExt::HandleMenuMsg ( UINT uMsg, WPARAM wParam, LPARAM lParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// res - подставная переменная типа LRESULT. Она не используется // (IContextMenu2::HandleMenuMsg() не предоставляет способа // возвращать результат), но она здесь для того, чтобы // код в MenuMessageHandler() мог быть одинаковым // независимо от того, через какой интерфейс // был получен вызов (IContextMenu2 или 3).
LRESULT res;
return MenuMessageHandler ( uMsg, wParam, lParam, &res ); }
STDMETHODIMP CBmpCtxMenuExt::HandleMenuMsg2 ( UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult ) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Для сообщений, которые не имеют возвращаемых значений, // pResult есть NULL. Это очень плохо со стороны MS, поскольку это // вынуждает нас проверять корректность pResult перед использованием. // Вы могли бы подумать, что указатель // к возвращаемому значению всегда должен бы быть действительным, // но нет. Если он NULL, я создаю подставную переменную, // поэтому код в MenuMessageHandler() всегда будет иметь // действительный указатель pResult .
if ( NULL == pResult ) { LRESULT res; return MenuMessageHandler ( uMsg, wParam, lParam, &res ); } else { return MenuMessageHandler ( uMsg, wParam, lParam, pResult ); } } |
MenuMessageHandler() просто пересылает WM_MEASUREITEM и WM_DROWITEM отдельным функциям-обработчикам сообщений.
|
STDMETHODIMP CBmpCtxMenuExt::MenuMessageHandler ( UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult ) { switch ( uMsg ) { case WM_MEASUREITEM: return OnMeasureItem ( (MEASUREITEMSTRUCT*) lParam, pResult ); break;
case WM_DRAWITEM: return OnDrawItem ( (DRAWITEMSTRUCT*) lParam, pResult ); break; }
return S_OK; } |
Как я отмечал раньше, документация говорит, что оболочка должна позволять нашему расширению оперировать с WM_INITMENUPOPUP и WM_MENUCHAR. Но за все время моих опытов я никогда не видел, чтобы эти сообщения приходили.
