- •Методические указания для выполнения лабораторной работы №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 в зависимости от их типа»
- •Как установить
- •Подробности реализации
- •Задания для лабораторных работ
- •Содержание отчета
Регистрация расширения оболочки
Регистрация нашего "вьювера битмапов" делается так же, как и других расширений контекстных меню. Вот RGS сценарий для этой работы:
|
HKCR { NoRemove Paint.Picture { NoRemove ShellEx { NoRemove ContextMenuHandlers { BitmapPreview = s '{D6F469CD-3DC7-408F-BB5F-74A1CA2647C9}' } } } }
|
Заметьте, что тип файлов "Paint.Picture" здесь жестко закодирован. Если вы не используете Paint, как вьювер по умолчанию для BMP-файлов, то вам необходимо изменить "Paint.Picture" на то, что указано в значении по умолчанию в ключе HKCR\.bmp.
Расширение 2 - Обработка щелчка правой кнопкой мыши на фоне окна каталога.
В оболочке вы можете модифицировать контекстное меню, отображаемое, когда вы щелкаете правой кнопкой мыши на рабочем столе или любом окне проводника, в котором просматривается каталог файловой системы. Программирование этого вида расширений подобно другим расширениям контекстного меню. Вот два основных отличия:
Параметры в IShellExtInit::Initialize() использованы иначе. Расширение регистрируется под другим ключом.
Отличия в iShellExtInit::Initialize()
Метод Initialize() имеет параметр pidlFolder, который до этого времени мы игнорировали, потому что он был NULL. Сейчас, наконец-то, этот параметр пригодится! Это PIDL каталога, где произошел щелчок правой кнопкой мыши. Второй параметр (IDataObject*) - NULL, потому что не было выбрано ни одного файла.
Вот реализация Initialize():
|
STDMETHODIMP CBkgndCtxMenuExt::Initialize ( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDO, HKEY hkeyProgID ) { // pidlFolder - PIDL каталога, на котором был щелчок. pDO - // NULL, т.к. не было указано с чем работать. // Мы получаем обычный путь к каталогу из его PIDL с помощью // SHGetPathFromIDList() API.
return SHGetPathFromIDList ( pidlFolder, m_szDirClickedIn ) ? S_OK : E_INVALIDARG; } |
Функция SHGetPathFromIDList() получает полный путь папки, который мы сохраняем для дальнейшего использования. Возвращаемое этой функцией BOOL-значение используется для индикации успеха или неудачи операции.
Отличия в регистрации.
Этот тип расширений регистрируется под другим ключом - а именно HKCR\Directory\Background\ShellEx\ContextMenuHandlers. Вот RGS сценарий для регистрации:
|
HKCR { NoRemove Directory { NoRemove Background { NoRemove ShellEx { NoRemove ContextMenuHandlers { ForceRemove SimpleBkgndExtension = s '{9E5E1445-6CEA-4761-8E45-AA19F654571E}' } } } } } |
За исключением этих двух отличий, расширение работает также, как и другие расширения контекстного меню. Хотя все же есть одна ловушка в IContextMenu::QueryContextMenu(). Похоже параметр uIndex всегда равен -1 (0xFFFFFFFF). Передача -1 в качестве индекса в InsertMenu() означает, что новый пункт будет расположен в самом низу меню. Однако, если вы инкрементируете uIndex, он переполнится и станет равным нулю, означая, что если вы снова передадите uIndex в InsertMenu(), то второй пункт появится в самом верху меню. Посмотрите в демонстрационном проекте код для QueryContextMenu() чтобы видеть, как правильно добавить пункты меню на нужное место.
Вот как выглядит модифицированное контекстное меню, с двумя добавленными пунктами в конце. Отмечу, что, IMHO, добавление пунктов в конец меню таким образом имеет значительные проблемы в удобстве использования. Предположим, пользователь хочет указать пункт "Properties". Обычные действия в этом случае - это щелчок правой кнопкой мыши и затем выбор последнего пункта меню. Когда появляется наше расширение и добавляет пункты после "Properties", мы заставляем привычку пользователя работать неправильно, что может причинить расстройство и вызвать несколько неприятных email-ов. ;)
Вы должны, вероятно, сделать ваши пункты меню визуально выделяющимися (может быть с картинками), но все равно даже после этого привычка пользователя будет работатьь не так. Вы также заставляете пользователя отвлекаться от своей задачи и искать правильный пункт меню. Используйте этот тип расширения осторожно.
