有关在Windows 10中访问外壳上下文菜单的问题

时间:2018-10-10 14:11:56

标签: windows visual-c++ shell-extensions

我正在尝试检索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的“已发送给”中也给出了正确的数字!

似乎在顶层菜单显示之后和子菜单可见之前添加了这些“发送至”菜单项。有什么解决方法吗?预先感谢!

0 个答案:

没有答案