Фон:
- Попытка порта 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
?
Спасибо.