如何为多个外壳项目(而不是单个IShellItem)填充上下文菜单

时间:2019-03-08 13:15:39

标签: shell winapi com windows-shell

我知道如何在拥有一个 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);

还有viola;出现所选IShellItem的外壳上下文菜单:

enter image description here

但是如何对多个IShellItem执行

如果我选择了多个项目,则我的代码(根据定义)仍然只能理解一个外壳项目:

enter image description here

我该如何处理多个弹壳物品?我知道要让外壳填充菜单的唯一方法是当您拥有一个一个外壳项目时。

如何要求外壳程序创建一次同时用于多个项目的 IContextMenu 或填充HMENU?

奖金

外壳可以显示一个上下文菜单,该菜单适用于来自不同文件夹的项目:

enter image description here

Ping:@JoachimMarder

2 个答案:

答案 0 :(得分:2)

您需要使用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));

通常,您不必创建数组,例如在复制粘贴或拖放操作或上下文菜单打开调用(命名空间扩展名等)中,剪贴板或传入的数据对象。

答案 1 :(得分:0)

我发现了无法使用的原因:

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

从不同的文件夹中获取IContextMenuBindToHandler的文档中对此进行了标注:

  

BHID_SFUIObject

     

将使用限制为 GetUIObjectOf 。仅对所有项目都在同一文件夹中的平面项目数组 使用此处理程序类型。 1

1 强调我的

但这并不会阻止Windows自己的搜索结果以及Jam-Software的UltraSearch的搜索结果:

enter image description here

enter image description here

所以一定有可能。

但这可以用其他答案的一部分来回答问题。