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

Интерфейс взаимодействия с контекстным меню

Как только проводник инициализировал наше расширение, он вызовет методы IContextMenu, позволяющие добавить пункты в меню, обеспечивающие подсказку в строке состояния и выполняющие выбор пользователя.

Добавление IContextMenu к нашему расширению подобно добавлению IShellExtInit. Откроем SimpleShlExt.h и добавим выделенные строки:

class ATL_NO_VTABLE CSimpleShlExt :

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CSimpleShlExt, &CLSID_SimpleShlExt>,

public IDispatchImpl<ISimpleShlExt, &IID_ISimpleShlExt, &LIBID_SIMPLEEXTLib>,

public IShellExtInit,

public IContextMenu

{

BEGIN_COM_MAP(CSimpleShlExt)

COM_INTERFACE_ENTRY(ISimpleShlExt)

COM_INTERFACE_ENTRY(IDispatch)

COM_INTERFACE_ENTRY(IShellExtInit)

COM_INTERFACE_ENTRY(IContextMenu)

END_COM_MAP()

А затем добавим прототипы методов IContextMenu:

public:

// IContextMenu

STDMETHOD(GetCommandString)(UINT, UINT, UINT*, LPSTR, UINT);

STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO);

STDMETHOD(QueryContextMenu)(HMENU, UINT, UINT, UINT, UINT);

Модификация контекстного меню

IContextMenu имеет 3 метода. Первый из них, QueryContextMenu(), позволяет модифицировать меню. Вот его прототип:

HRESULT IContextMenu::QueryContextMenu (

HMENU hmenu,

UINT uMenuIndex,

UINT uidFirstCmd,

UINT uidLastCmd,

UINT uFlags );

hmenu это дескриптор контекстного меню. uMenuIndex - позиция, с которой мы должны начать добавлять свои пункты. uidFirstCmd и uidLastCmd - интервал идентификаторов команд, которые мы можем использовать для наших пунктов меню. uFlags указывает, почему проводник вызывает QueryContextMenu(), но об этом позже.

Описания возвращаемого значения различны в различных источниках. В книге Dino Esposito говорится, что это число пунктов меню, добавленных QueryContextMenu(). Библиотека MSDN, поступающая с VC6, говорит, что это ID последнего пункта меню, который мы добавим, плюс 1. Поздние on-line документы MSDN говорят:

"Установите значение кода (возвращаемого через HRESULT) равным значению самого большего идентификатора команды, плюс 1. Например, idCmdFirst установлен в 5 и вы добавляете к меню 3 пункта с ID = 5, 7 и 8. Возвращаемое значение должно быть MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 - 5 + 1)."

Я следовал объяснениям Dino в коде, написанном мною. Его метод получения возвращаемого значения эквивалентен методу on-line MSDN до тех пор, пока вы считаете количество пунктов вашего меню с помощью uidFirstCmd и прибавляете 1 для каждого добавленного пункта. Наше простое расширение будет иметь только один пункт, поэтому функция QueryContextMenu() совсем проста:

HRESULT CSimpleShlExt::QueryContextMenu (

HMENU hmenu,

UINT uMenuIndex,

UINT uidFirstCmd,

UINT uidLastCmd,

UINT uFlags )

{

// If the flags include CMF_DEFAULTONLY then we shouldn't do anything.

if ( uFlags & CMF_DEFAULTONLY )

{

return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

}

InsertMenu ( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd, _T("SimpleShlExt Test Item") );

return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 1 );

}

Первое, что мы делаем - это проверяем uFlags. Вы можете найти полный список флагов в MSDN, но для контекстного меню важно только одно значение - CMF_DEFAULTONLY. Этот флаг сообщает расширениям, что добавляются только пункты меню по-умолчанию. Расширение ничего не должно добавлять, если этот флаг присутствует. Вот почему мы немедленно возвращаем 0, если выставлен это флаг. Если этого флага нет, мы модифицируем меню (используя hmenu), и возвращаем 1, чтобы сообщить оболочке, что мы добавили 1 пункт меню.

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