Как правильно перечислить элементы в пространстве имен оболочки? - PullRequest
0 голосов
/ 21 марта 2019

Фон:

  • Попытка порта CMFCShellTreeCtrl .
  • С одним и тем же элементом оболочки могут быть связаны несколько GUID.Например, «Загрузки» имеют следующие два GUID:
    • :: {374DE290-123F-4565-9164-39C4925E467B}
    • :: {088E3905-0323-4B02-9826-5D99428E115F}

Когда я попытался перечислить элементы оболочки в разделе «Этот компьютер» / «Мой компьютер» с помощью приведенного ниже кода, каждый элемент появлялся столько же раз, сколько и связанных идентификаторов GUID.с этим.Например, «Загрузки» появлялись дважды, в то время как «C: \» появлялся один раз.

#include <iostream>
#include <ShlObj.h>

void test2() {
    SFGAOF sfgao;
    LPITEMIDLIST this_pc_pidl;
    SHParseDisplayName(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), NULL, &this_pc_pidl, SFGAO_FILESYSTEM, &sfgao);

    LPSHELLFOLDER this_pc_folder;
    SHBindToObject(NULL, this_pc_pidl, NULL, IID_IShellFolder, (LPVOID*)&this_pc_folder);

    const SHCONTF m_dwFlags = SHCONTF_FOLDERS;
    LPENUMIDLIST this_pc_enum;
    if (FAILED(this_pc_folder->EnumObjects(NULL, m_dwFlags, &this_pc_enum)) || this_pc_enum == NULL) {
        return;
    }

    LPITEMIDLIST sub_pidl_rel;
    DWORD dw_fetched;
    while ((SUCCEEDED(this_pc_enum->Next(1, &sub_pidl_rel, &dw_fetched)) && dw_fetched)) {
        STRRET ret;
        std::basic_string<TCHAR> s;

        if (S_OK == (this_pc_folder->GetDisplayNameOf(sub_pidl_rel, SHGDN_FORPARSING | SHGDN_INFOLDER, &ret)))
        {
            switch (ret.uType) {
            case STRRET_CSTR:
                s =  L"{CSTR}";
                break;
            case STRRET_OFFSET:
                s = L"{OFFSET}";
                break;
            case STRRET_WSTR:
                s = ret.pOleStr;
                break;
            default:
                s = L"{WTF}" + std::to_wstring(ret.uType);
                break;
            }
        }

        std::wcout << '<' << s << '>' << std::endl;
    }
}

Играя с исходным кодом CMFCShellTreeCtrl, где интерфейс IShellFolder выполняет тяжелую работу, я обнаружил, что даже официальный MFCкласс показывает, что раздражающее поведение (одно и то же имя появляется дважды) также, если используется следующая настройка:

  • «Этот компьютер» перечисляется во время, или после, или через 2 секунды в другом потоке, перечислениеего родительский элемент «Рабочий стол»

, но не в единственной последовательности операций:

  • «Этот ПК» перечисляется после прибытия соответствующего события пользовательского интерфейса.

Одним словом, IShellFolder::EnumObjects дает РАЗНЫЕ результаты для ЖЕ ОДНОЙ папки оболочки в обстоятельствах с кажущейся несущественной разницей.

Так как же CMFCShellTreeCtrl, который кажется недетерминированным и невозможным дляфункционировать правильно, как-то правильно себя вести только при том единственном обстоятельстве, которое совпадает с единственно возможным действием пользователя?Кроме того, в CLI вместо GUI, как можно правильно перечислять элементы в пространстве имен оболочки, например CMFCShellTreeCtrl?

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...