Быстрый доступ и расширения пространства имен: открепление объекта

Когда я щелкаю правой кнопкой мыши по файлу lnk - ссылка на виртуальную папку с расширением пространства имен -, тогда функции CreateViewObject и / или GetUiObjectOf из моего IShellFolder/IShellFolder2 реализации называются. Эти функции вызываются с IID_IContextMenu как параметр (riid), Кроме того, когда QueryContextMenu вызывается флаг CMF_VERBSONLY (0x00000002) установлено. Это означает, что 1) я знаю, что должно быть показано меню и 2) что из-за флага CMF_VERBSONLY что это меню было запрошено файлом.lnk и что (источник Microsoft):

0x00000002. Контекстное меню является файлом ярлыка (обычно это файл.lnk). Обработчики контекстного меню должны игнорировать это значение.

Большую часть времени я не добавляю пункты меню, когда этот флаг присутствует. Если щелкнуть правой кнопкой мыши файл.lnk, Windows вернет стандартное меню для файлов.lnk, и будет предложена возможность удалить этот файл. У меня была такая же возможность с папкой "Избранное" в Windows 7. Начиная с Windows 10 и "введения" быстрого доступа, это больше невозможно. Пункт меню "Открепить" не будет отображаться по умолчанию.

Поскольку это очень сложно из расширения пространства имен, предполагая, IID_IContextMenu а также CMF_VERBSONLY чтобы узнать, закреплен ли объект в быстром доступе, а также как открепить его - мне, вероятно, придется открыть папку автоматических списков переходов, а затем проверить все файлы списка переходов по отображаемому имени моего объекта - мне было интересно, есть ли более простой способ справиться с этим (в конце списка переходов конкатенация файлов LNK).

Спасибо за вашу помощь

1 ответ

Благодаря подсказке Саймона Мурье, здесь возможный способ проверить, закреплена ли папка (любого типа) в быстром доступе или нет...

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();
    }
}
Другие вопросы по тегам