Как заполнить контекстное меню для нескольких элементов оболочки (вместо одного IShellItem) - PullRequest
0 голосов
/ 08 марта 2019

Я знаю, как добавить контекстное меню оболочки, когда у вас есть один IShellItem объект.Основная процедура:

Код образца:

//I've right-clicked something that represents one shell item.
//Make a context menu appear appropriate for that item

//Get the IContextMenu handler for this shell item
IContextMenu contextMenu;
HRESULT hr = shellItem.BindToHandler(null, BHID_SFUIObject, IContextMenu, out contextMenu);
OleCheck(hr);

//Create a popup menu
HMENU menu = CreatePopupMenu();
if (menu == 0) ThrowLastError();

//Have the shell IContextMenu stuff things into our hmenu
hr = contextMenu.QueryContextMenu(menu, 0, 1, 0x7FFF, CMF_EXPLORE || CMF_ITEMMENU);
OleCheck(hr);

//Now we can show the context menu
TrackPopupMenu(menu, TPM_LEFTALIGN || TPM_LEFTBUTTON || TPM_RIGHTBUTTON || TPM_RETURNCMD, pos.X, pos.Y, 0, callbackWindow, null);

и альт ;появляется контекстное меню оболочки для выбранного IShellItem :

enter image description here

Но как это сделать для несколькихIShellItems

Если я выбираю несколько элементов, мой код (по определению) все еще понимает только один элемент оболочки:

enter image description here

Как я могуобрабатывать несколько предметов снарядов?Единственный способ, которым я знаю, чтобы оболочка заполняла меню, это когда у вас есть один элемент оболочки.

Как попросить оболочку создать IContextMenu , илизаполнить HMENU, то есть для нескольких элементов одновременно?

Бонус

В оболочке может отображаться контекстное меню, которое применяется к элементам из разных папок:

enter image description here

Бонусное чтение

Ответы [ 2 ]

2 голосов
/ 08 марта 2019

Вам нужно использовать интерфейс IShellItemArray , так что-то вроде этого для двух элементов:

// get two Shell Items and get their respective absolute PIDLs
CComPtr<IShellItem> item1;
HRCHECK(SHCreateItemFromParsingName(L"c:\\myPath1\\myFile1.myExt1", NULL, IID_PPV_ARGS(&item1)));

CComQIPtr<IPersistIDList> idl1(item1);
CComHeapPtr<ITEMIDLIST_ABSOLUTE> spidl1;
HRCHECK(idl1->GetIDList(&spidl1));

CComPtr<IShellItem> item2;
HRCHECK(SHCreateItemFromParsingName(L"c:\\myPath2\\myFile2.myExt2", NULL, IID_PPV_ARGS(&item2)));

CComQIPtr<IPersistIDList> idl2(item2);
CComHeapPtr<ITEMIDLIST_ABSOLUTE> spidl2;
HRCHECK(idl2->GetIDList(&spidl2));

// build a Shell Item Array from them
LPCITEMIDLIST list[2];
list[0] = spidl1;
list[1] = spidl2;
CComPtr<IShellItemArray> array;
HRCHECK(SHCreateShellItemArrayFromIDLists(2, list, &array));

// get the menu object
CComPtr<IContextMenu> menu;
HRCHECK(array->BindToHandler(NULL, BHID_SFUIObject, IID_PPV_ARGS(&menu)));

// ... etc ...
HMENU hMenu= CreatePopupMenu();
HRCHECK(menu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE || CMF_ITEMMENU));

Как правило, вам не нужно создавать массивы, как в операциях копирования, вставки или перетаскивания, или вызовах открытия контекстного меню (расширения пространства имен и т. Д.), Массив присутствует в буфере обмена или в переданный объект данных.

0 голосов
/ 05 мая 2019

Я нашел причину, по которой вы не можете использовать:

shellItem.BindToHandler(null, BHID_SFUIObject, IContextMenu, out contextMenu);

, чтобы получить IContextMenu для элементов из разных папок. Это вызывается в документации BindToHandler:

BHID_SFUIObject

Ограничивает использование до GetUIObjectOf. Используйте этот тип обработчика только для массива плоских элементов, , где все элементы находятся в одной папке. 1

1 упорная мина

Но это не мешает собственным результатам поиска Windows, а также тому, что Jam-Software UltraSearch делает это:

enter image description here

enter image description here

Так что это должно быть возможно.

Но это отвечает на вопрос частью другого ответа.

...