快速访问和命名空间扩展:取消固定 object

Quick Access and Namespace Extensions: Unpin object

当我右键单击一个 lnk 文件 - link 在命名空间扩展中的一个虚拟文件夹上 - 然后 CreateViewObject and/or GetUiObjectOf 的函数 CreateViewObject and/or GetUiObjectOf =13=] 实现被调用。这些函数使用 IID_IContextMenu 作为参数 (riid) 调用。此外,当 QueryContextMenu 被调用时,标志 CMF_VERBSONLY (0x00000002) 被设置。这意味着 1) 我知道应该显示一个菜单,并且 2) 由于标志 CMF_VERBSONLY,该菜单被 .lnk 文件查询,并且(来源 Microsoft):

0x00000002. The shortcut menu is that of a shortcut file (normally, a .lnk file). Shortcut menu handlers should ignore this value.

大多数情况下,出现此标志时我不会添加菜单项。当 right-clicking 处理 .lnk 文件时,windows 将 return .lnk 文件的标准菜单,并提供删除此文件的机会。我对 Windows 7 上的收藏夹文件夹有同样的机会。由于 Windows 10 和 "introduction" 的快速访问,它不再可能了。默认情况下不会显示 "Unpin" 个菜单项。

因为命名空间扩展非常困难,假设 IID_IContextMenuCMF_VERBSONLY 知道 object 是否固定在快速访问中以及如何取消固定 - 我可能会必须打开自动跳转列表文件夹,然后根据我的 object displayname - 检查所有跳转列表文件,我想知道是否有更简单的方法来处理这个问题(最后跳转列表是 lnk 文件的串联).

感谢您的帮助

感谢 Simon Mourier 的提示,这里提供了一种检查文件夹(任何类型)是否固定在快速访问中的可能方法...

extern bool __cdecl IsInQuickAccess(LPWSTR folderParsingName)
{
    IShellFolder* desktopFolder;
    HRESULT hr = SHGetDesktopFolder(&desktopFolder);
    bool isInQuickAccess = false;

    if (SUCCEEDED(hr))
    {
        LPITEMIDLIST quickAccessIdList;
        hr = desktopFolder->ParseDisplayName(NULL, NULL, _T("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}"), NULL, &quickAccessIdList, NULL);

        if (SUCCEEDED(hr))
        {
            IShellFolder* quickAccessFolder;
            hr = desktopFolder->BindToObject(quickAccessIdList, NULL, IID_PPV_ARGS(&quickAccessFolder));

            if (SUCCEEDED(hr))
            {
                IEnumIDList* currentChildren = NULL;
                hr = quickAccessFolder->EnumObjects(NULL, SHCONTF_FOLDERS, &currentChildren);

                if (SUCCEEDED(hr))
                {
                    CString wPathToFolder = CharLower(folderParsingName);
                    LPITEMIDLIST childPidl = NULL;

                    while (!isInQuickAccess && currentChildren->Next(1, &childPidl, NULL) == S_OK)
                    {
                        STRRET childDisplayName;
                        hr = quickAccessFolder->GetDisplayNameOf(childPidl, SHGDN_FORPARSING, &childDisplayName);

                        if (SUCCEEDED(hr))
                        {
                            LPWSTR childDisplayNameString;
                            hr = StrRetToStr(&childDisplayName, NULL, &childDisplayNameString);

                            if (SUCCEEDED(hr))
                            {
                                LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);

                                if (wPathToFolder.Compare(childDisplayNameStringToLower) == 0)
                                    isInQuickAccess = true;

                                CoTaskMemFree(childDisplayNameString);
                            }
                        }
                    }

                    CoTaskMemFree(childPidl);
                    currentChildren->Release();
                }
                quickAccessFolder->Release();
            }
            CoTaskMemFree(quickAccessIdList);
        }
        desktopFolder->Release();
    }
    return isInQuickAccess;
}

并在此处取消固定主页(检查具有给定显示名称的文件夹是否处于快速访问状态)。

extern void __cdecl UnpinFromHome(LPWSTR folderParsingName)
{
    IShellFolder* desktopFolder;
    HRESULT hr = SHGetDesktopFolder(&desktopFolder);

    if (SUCCEEDED(hr))
    {
        LPITEMIDLIST quickAccessIdList;
        hr = desktopFolder->ParseDisplayName(NULL, NULL, _T("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}"), NULL, &quickAccessIdList, NULL);

        if (SUCCEEDED(hr))
        {
            IShellFolder* quickAccessFolder;
            hr = desktopFolder->BindToObject(quickAccessIdList, NULL, IID_PPV_ARGS(&quickAccessFolder));

            if (SUCCEEDED(hr))
            {
                IEnumIDList* currentChildren = NULL;
                hr = quickAccessFolder->EnumObjects(NULL, SHCONTF_FOLDERS, &currentChildren);

                if (SUCCEEDED(hr))
                {
                    CString wPathToFolder = CharLower(folderParsingName);
                    LPITEMIDLIST childPidl = NULL;
                    bool isInQuickAccess = false;

                    while (!isInQuickAccess && currentChildren->Next(1, &childPidl, NULL) == S_OK)
                    {
                        STRRET childDisplayName;
                        hr = quickAccessFolder->GetDisplayNameOf(childPidl, SHGDN_FORPARSING, &childDisplayName);

                        if (SUCCEEDED(hr))
                        {
                            LPWSTR childDisplayNameString;
                            hr = StrRetToStr(&childDisplayName, NULL, &childDisplayNameString);

                            if (SUCCEEDED(hr))
                            {
                                LPWSTR childDisplayNameStringToLower = CharLower(childDisplayNameString);

                                if (wPathToFolder.Compare(childDisplayNameStringToLower) == 0)
                                {
                                    IContextMenu* childContextMenu;
                                    LPCITEMIDLIST childCPidl = childPidl;
                                    hr = quickAccessFolder->GetUIObjectOf(NULL, 1, &childCPidl, IID_IContextMenu, NULL, (void**)&childContextMenu);

                                    if (SUCCEEDED(hr))
                                    {
                                        HMENU hmenu = CreatePopupMenu();
                                        if (hmenu)
                                        {
                                            hr = childContextMenu->QueryContextMenu(hmenu, 0, 1, 0x7FFF, CMF_NORMAL);
                                            if (SUCCEEDED(hr))
                                            {
                                                CMINVOKECOMMANDINFO info = { 0 };
                                                info.cbSize = sizeof(info);
                                                info.hwnd = NULL;
                                                info.lpVerb = "unpinfromhome";
                                                info.nShow = 1;
                                                info.fMask = CMIC_MASK_ASYNCOK;
                                                childContextMenu->InvokeCommand(&info);
                                            }
                                            DestroyMenu(hmenu);
                                        }

                                    }
                                    isInQuickAccess = true;
                                }
                                CoTaskMemFree(childDisplayNameString);
                            }
                        }
                    }
                    CoTaskMemFree(childPidl);
                    currentChildren->Release();
                }
                quickAccessFolder->Release();
            }
            CoTaskMemFree(quickAccessIdList);
        }
        desktopFolder->Release();
    }
}