- •Методические указания для выполнения лабораторной работы №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, который может быть вызван, это GetCommandString(). Если пользователь щелкает правой кнопкой на текстовом файле в окне проводника (в правом окне, если режим двухоконный), или укажет текстовый файл, а затем щелкнет на пункте меню File, то в строке состояния появится подсказка. Наша GetCommandString() возвратит строку, отображаемую в подсказке.
Прототип GetCommandString():
|
HRESULT IContextMenu::GetCommandString ( UINT idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax ); |
где idCmd - начинающийся с 0 счетчик, который указывает, какой пункт меню отмечен. Поскольку у нас только один пункт меню, idCmd всегда будет =0. Но если у нас есть изначально, скажем, 3 пункта меню, то idCmd может быть равен 0, 1 или 2. uFlags - другая группа флагов, которую я опишу позже. pwReserved можно проигнорировать. pszName - указатель на собственный буфер оболочки, где мы сохраним строку подсказки, которая будет высвечиваться. cchMax - это размер буфера. Возвращаемое функцией значение - одна из обычных констант HRESULT - S_OK или E_FAIL.
GetCommandString() также может быть вызвана, чтобы получить "действие" ("verb") от пункта меню. "Действие" - независимая от языка строка, которая идентифицирует операцию, производимую с файлом. Документы по ShellExecute() расскажут об объекте "действие" больше и это тема для другой статьи, но сокращенная версия такова: "действия" могут быть внесены в список в реестре ("open", "print") или могут быть созданы расширением динамически . Это позволяет вызывать расширение при выполнении ShellExecute().
Во всяком случае, причина по которой я обо всем этом упомянул состоит в том, что нам нужно определить, для чего вызывается GetCommandString(). Если проводник требует строку подсказки, мы дадим ее. Если проводник потребует "действие" мы проигнорируем его запрос. Это как раз тот момент, когда параметр uFlags становится значимым. Если в параметре uFlags установлен бит GCS_HELPTEXT то проводник запрашивает подсказку. Если установлен бит GCS_UNICODE , мы должны возвратить строку в UNICODE.
Код нашей GetCommandString() выглядит так:
|
#include <atlconv.h> // for ATL string conversion macros
HRESULT CSimpleShlExt::GetCommandString ( UINT idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax ) { USES_CONVERSION;
// Check idCmd, it must be 0 since we have only one menu item. if ( 0 != idCmd ) return E_INVALIDARG;
// If Explorer is asking for a help string, copy our string into the // supplied buffer. if ( uFlags & GCS_HELPTEXT ) { LPCTSTR szText = _T("This is the simple shell extension's help");
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(szText), cchMax ); } else { // Use the ANSI string copy API to return the help string. lstrcpynA ( pszName, T2CA(szText), cchMax ); }
return S_OK; }
return E_INVALIDARG; } |
Здесь нет ничего фантастического. Я просто преобразовываю строку в подходящий набор символов. Если вы никогда не использовали ATL макросов конвертирования, вы определенно должны прочитать о них, т.к. они намного облегчают жизнь, когда необходимо передать строку UNICODE COM-методам и OLE-функциям. Я использую T2CW и T2CA в коде, приведенном выше, чтобы преобразовать строку в UNICODE и ANSI соответственно. Макрос USES_CONVERSION в начале функции объявляет локальную переменную, которая используется в конверсионных макросах.
Заметим одну важную вещь: lstrcpyn() гарантирует, что строка назначения будет завершена нулем. В этом ее отличие от CRT-функции strncpy(), которая не добавляет завершающий 0, если длина исходной строки больше или равна cchMax. Я предлагаю всегда использовать lstrcpyn(), и вам не нужно будет проверять конец строки после каждого вызова strncpy(), чтобы убедиться, что она закрыта нулем.
