Почему PIDL для панели управления будет отличаться?


Я вижу, что нужно сделать это , чтобы сравнить PIDLs: IShellFolder::CompareIDs().

В частности, я пытаюсь определить, является ли данный абсолютный PIDL (или относительный) Pidl панели управления. Однако на практике я получаю два Pidl, которые ishellfolder:: CompareIDs() утверждает, что они не равны, когда они должны быть (глядя на GetDisplayName() для каждого, я вижу, что мы действительно смотрим на панель управления).

В принципе, я получаю абсолютный PIDL на панели управления:

PIDL iidControlPanel = nullptr;
SHGetSpecialFolderLocation(hwnd, CSIDL_CONTROLS, &iidControlPanel);

И затем сравнение входящего перечисляемого объекта оболочки, например (см. здесь для контекста-в двух словах это смотрит на результаты перечисления пространства имен оболочки рабочего стола внутри CMFCShellTreeCtrl):

bool bIsControlPanel = CompareAbsolutePIDLs(iidControlPanel, pItem->pidlFQ);

Для справки, вот функция сравнения:

bool CompareAbsolutePIDLs(PIDLIST_ABSOLUTE pidl1, PIDLIST_ABSOLUTE pidl2)
{
    CComPtr<IShellFolder> ishDesk;
    SHGetDesktopFolder(&ishDesk);
    HRESULT hr = ishDesk->CompareIDs(SHCIDS_CANONICALONLY, pidl1, pidl2);
    return SUCCEEDED(hr) && HRESULT_CODE(hr) == 0;
}

В отладчике я вижу, что GetDisplayName () для каждого возвращает:

"::{26EE0668-A00A-44D7-9371-BEB064C98683}"
"::{26EE0668-A00A-44D7-9371-BEB064C98683}"

Здесь вы можете увидеть шестнадцатеричный дамп PIDLs:

1f 70 68 06 ee 26 0a a0 d7 44 93 71 be b0 64 c9 86 83 *0c* 00
1f 70 68 06 ee 26 0a a0 d7 44 93 71 be b0 64 c9 86 83 *00* 00

В базовые PIDL также являются двоичными идентичными, за исключением предпоследнего значения (00 против 0c). Я в настоящее время в недоумении, почему они отличаются, или что я могу сделать, чтобы решить эту проблему?!

Вопросы

  1. Есть ли другой способ получить PIDL элемента управления it таким образом, чтобы не включать этот кажущийся ложным дополнительный нулевой байт?
  2. С другой стороны, есть ли лучший способ получить PIDL элемента перечисления (есть ли что-то недостаточное в том, что CMFCShellTreeCtrol получает абсолютный PIDL таким образом, что он не может включить последний нулевой байт?)
  3. Есть ли способ получить панель управления в виде относительного PIDL, а затем сравнить ее с относительным перечислением PIDL (которое у меня также есть)?
  4. ???
1 5

1 ответ:

Это действительно разные объекты оболочки. Вы можете передать Pidl, которые вы получили в SHGetNameFromIDList () с опцией SIGDN_NORMALDISPLAY, чтобы преобразовать их в читаемые строки. Длинный PIDL (с 0x0c) преобразуется в "все элементы панели управления", короткий-в"Панель управления".

Эта проблема началась с использования SHGetSpecialFolderLocation () для извлечения виртуальной папки для элементов управления панели управления. Отличается от объекта панели управления в корне рабочего стола. Я думаю вы должны исправить это, получив PIDL для Панели управления и игнорировать виртуальную папку. Один из способов сделать это-с помощью ILCloneFirst преобразовать виртуальную папку в корневой объект:

 PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);

Или вы можете жестко закодировать CLSID панели управления,":: {26EE0668-A00A-44D7-9371-BEB064C98683}", и преобразовать его в PIDL с помощью SHParseDisplayName().