- •Методические указания для выполнения лабораторной работы №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 в зависимости от их типа»
- •Как установить
- •Подробности реализации
- •Задания для лабораторных работ
- •Содержание отчета
Пример 7 «Owner-drawn меню в расширениях контекстных меню и по созданию расширения контекстного меню, которое отзывается на правый щелчок на фоне окна каталога» Расширение 1 - Пункты меню owner-drawn.
В этой части рассмотрим дополнительную работу, необходимую для реализации owner-drawn меню.
Поскольку это расширение реализует owner-drawn меню, нам придется иметь дело с графикой. Я решил скопировать что-нибудь из того, что делает программа PicaView: Показать эскиз графического файла в контекстном меню. Вот как выглядят пункты меню PicaView:
Это расширение создаст эскиз файла ВМР. Чтобы упростить код я не буду беспокоиться о пропорциях и сочетании цветов.
Использование AppWizard
Запустите AppWizard и создайте новый ATL COM проект. Назовем его BmpViewerExt. Щелкните ОК, чтобы перейти к первому (и единственному) диалогу мастера. Пометьте переключатель "Support MFC" и затем щелкните Finish. Теперь у нас есть пустой ATL проект, который построит DLL, но нам необходимо еще добавить наш COM объект-расширение. В дереве ClassView щелкните правой кнопкой мыши на пункте BmpViewerExt classes и укажите New ATL Object.
В мастере ATL Object на первой панели уже выбран Simple Object, поэтому просто щелкните Next. На второй панели в поле редактирования Short Name введите BmpCtxMenuExt и щелкните ОК (остальные поля заполнятся автоматически). Эти действия создадут класс CBmpCtxMenuExt, который содержит основной код для реализации COM объектов. Мы добавим наш код в этот класс.
Интерфейс инициализации.
Как и для предыдущих расширений контекстных меню, это расширение реализует интерфейс IShellExtInit. Чтобы добавить IShellExtInit к нашему COM объекту, откройте BmpCtxMenuExt.h и добавьте выделенные строки. Несколько переменных, которые здесь указаны, мы будем использовать позже, в процессе рисования пункта меню.
|
#include <comdef.h>
///////////////////////////////////////////////////////////////////////////// // CBmpCtxMenuExt
class ATL_NO_VTABLE CBmpCtxMenuExt : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CBmpCtxMenuExt, &CLSID_BmpCtxMenuExt>, public IDispatchImpl<IBmpCtxMenuExt, &IID_IBmpCtxMenuExt, &LIBID_BMPVIEWEREXTLib>, public IShellExtInit { BEGIN_COM_MAP(CBmpCtxMenuExt) COM_INTERFACE_ENTRY(IBmpCtxMenuExt) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellExtInit) END_COM_MAP()
public: // IShellExtInit STDMETHOD(Initialize)(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
protected: TCHAR m_szFile[MAX_PATH]; CBitmap m_bmp; UINT m_uOurItemID;
LONG m_lItemWidth, m_lItemHeight; LONG m_lBmpWidth, m_lBmpHeight;
static const LONG m_lMaxThumbnailSize; static const LONG m_l3DBorderWidth; static const LONG m_lMenuItemSpacing; static const LONG m_lTotalBorderSpace;
// Helper functions for handling the menu-related messages. STDMETHOD(MenuMessageHandler)(UINT, WPARAM, LPARAM, LRESULT*); STDMETHOD(OnMeasureItem)(MEASUREITEMSTRUCT*, LRESULT*); STDMETHOD(OnDrawItem)(DRAWITEMSTRUCT*, LRESULT*); }; |
Что нам предстоит сделать в IShellExtInit::Initialize(), так это получить имя выбранного файла, и если это BMP-файл, создать его эскиз.
В файл BmpCtxMenuExt.cpp добавим объявления для следующих статических переменных. Они управляют визуальными аспектами эскиза и его границами. Не стесняясь измените эти значения, и проследите, как это отразится на конечном результате в меню.
|
const LONG CBmpCtxMenuExt::m_lMaxThumbnailSize = 64; const LONG CBmpCtxMenuExt::m_l3DBorderWidth = 2; const LONG CBmpCtxMenuExt::m_lMenuItemSpacing = 4; const LONG CBmpCtxMenuExt::m_lTotalBorderSpace = 2*(m_lMenuItemSpacing+m_l3DBorderWidth); |
Эти константы означают следующее:
m_lMaxThumbnailSize: Если картинка больше (в любом измерении), чем это число, она будет сжата до такой степени, чтобы каждая сторона квадрата была m_lMaxThumbnailSize пикселей. Если картинка меньше (в обоих измерениях) она будет оставлена без изменений. m_l3DBorderWidth: Толщина объемной границы, которая будет сделана по периметру эскиза, в пикселях. m_lMenuItemSpacing: Число пикселей, составляющих пустое пространство вокруг объемной границы. Это обеспечит небольшой зазор между эскизом и окружающими его пунктами меню.
Также добавим определение функции IShellExtInit::Initialize():
|
STDMETHODIMP CBmpCtxMenuExt::Initialize ( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDO, HKEY hkeyProgID ) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
COleDataObject dataobj; HGLOBAL hglobal; HDROP hdrop; bool bOK = false;
dataobj.Attach ( pDO, FALSE ); // FALSE = don't release IDataObject interface when destroyed
// Get the first selected file name. I'll keep this simple and just check // the first name to see if it's a .BMP. hglobal = dataobj.GetGlobalData ( CF_HDROP );
if ( NULL == hglobal ) return E_INVALIDARG;
hdrop = (HDROP) GlobalLock ( hglobal );
if ( NULL == hdrop ) return E_INVALIDARG;
// Get the name of the first selected file. if ( DragQueryFile ( hdrop, 0, m_szFile, MAX_PATH )) { // Is its extension .BMP? if ( PathMatchSpec ( m_szFile, _T("*.bmp") )) { // Load the bitmap and attach our CBitmap object to it. HBITMAP hbm = (HBITMAP) LoadImage ( NULL, m_szFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
if ( NULL != hbm ) { // We loaded the bitmap, so attach the CBitmap to it. m_bmp.Attach ( hbm ); bOK = true; } } }
GlobalUnlock ( hglobal );
return bOK ? S_OK : E_FAIL; } |
Код здесь вполне прямолинейный. Мы загружаем картинку из файла и подключаем к ней объект CBitmap для дальнейшей работы.
