Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП - методички / OS&SP_Lab_2.6(shell).doc
Скачиваний:
95
Добавлен:
18.05.2015
Размер:
1.12 Mб
Скачать

Пример 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 для дальнейшей работы.

Соседние файлы в папке ОСиСП - методички