我正在尝试检索shell上下文菜单,因为我只需要HMENU即可获取菜单项(包括子菜单中的项)的名称和图标,因此不会显示该菜单。网上有很多关于此事的文章,在这些文章之后,我已经成功地使其中的大部分工作发挥了作用。
通过提供所选项目的PIDL和一个空的HMENU,我的代码可以毫无问题地获得Shell上下文菜单的顶层。
// Callee need to DestroyMenu(hTopMenu);
HRESULT FillContextMenuFromPIDL(LPCITEMIDLIST pidl, HMENU hTopMenu)
{
HRESULT ret = MAKE_HRESULT(SEVERITY_ERROR, 0, 0);
IContextMenu *pcm;
HRESULT hr;
IShellFolder *psf;
LPCITEMIDLIST pidlChild;
if (SUCCEEDED(hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, &pidlChild))) {
hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, IID_IContextMenu, NULL, (void**)&pcm);
// 0 was hWnd
psf->Release();
if (SUCCEEDED(hr)) {
hr = pcm->QueryContextMenu(hTopMenu, 0, 1, 0x7FFF, 0x00020490);
if (SUCCEEDED(hr)) {
IContextMenu3* hContextMenu3 = NULL;
IContextMenu2* hContextMenu2 = NULL;
if (SUCCEEDED(pcm->QueryInterface(IID_IContextMenu3, (void**)&hContextMenu3))) {
LRESULT lres;
hContextMenu3->HandleMenuMsg2(WM_INITMENUPOPUP, (WPARAM)hTopMenu, 0, &lres);
for (int pos = 0; pos < GetMenuItemCount(hTopMenu); pos++) {
HMENU subMenu = GetSubMenu(hTopMenu, pos);
if (subMenu != NULL) {
LPARAM lparam = (LPARAM)(MAKELONG(pos, FALSE));
hContextMenu3->HandleMenuMsg2(WM_INITMENUPOPUP, (WPARAM)subMenu, lparam, &lres);
}
}
//hContextMenu3->Release();
}
if (SUCCEEDED( pcm->QueryInterface(IID_IContextMenu2, (void**)&hContextMenu2) )) {
for (int pos = 0; pos < GetMenuItemCount(hTopMenu); pos++) {
HMENU subMenu = GetSubMenu(hTopMenu, pos);
if (subMenu != NULL) {
LPARAM lparam = (LPARAM)(MAKELONG(pos, FALSE));
hContextMenu2->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)subMenu, lparam);
}
}
//hContextMenu2->Release();
}
ret = MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
}
//pcm->Release();
}
}
return ret;
}
以前的程序员提到为了使“打开方式”和“发送至”起作用,您必须将WM_INITMENUPOPUP消息转发到WndProc中的IContextMenu2:HandleMenuMsg和IContextMenu3:HandleMenuMsg2。由于无法显示菜单,因此将WM_INITMENUPOPUP发送到这两个界面,并让它们添加动态菜单项。这适用于“打开方式”和“授予权限”,但不适用于“发送给”。 GetMenuItemCount()对于“发送到”返回1。
后来我做了一个实验,我钩住了桌面上的WndProc,并放下了所有WM_INITMENUPOPUP,这样原始的WndProc和HandleMenuMsg就看不到它们了。 “打开方式”和“授予权限”按预期停止工作,但是有趣的是,“发送给”子菜单项未受影响!另外,第一个WM_INITMENUPOPUP的GetMenuItemCount(HWND为“已发送”)为1,但即使在HandleMenuMsg没收到的情况下,它在WM_INITMENUPOPUP的“已发送给”中也给出了正确的数字!
似乎在顶层菜单显示之后和子菜单可见之前添加了这些“发送至”菜单项。有什么解决方法吗?预先感谢!