我看到应该做this来比较PIDL:IShellFolder::CompareIDs()。
特别是,我试图检测给定的绝对PIDL(或相对)是否是控制面板的绝对PIDL。
但是,在实践中,我最后得到两个PIDL,它们的IShellFolder::CompareIDs()声明不相等,当它们应该相等时(查看每个的GetDisplayName(),我可以看到我们确实在查看控制面板) 。
基本上,我通过以下方式获取“控制面板”的绝对PIDL:
PIDL iidControlPanel = nullptr;
SHGetSpecialFolderLocation(hwnd, CSIDL_CONTROLS, &iidControlPanel);
然后像这样比较传入的枚举shell对象(请参见here以获取上下文-简而言之,这是在枚举CMFCShellTreeCtrl内部的桌面shell命名空间的结果):
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}\0"
"::{26EE0668-A00A-44D7-9371-BEB064C98683}"
在这里,您可以看到PIDL的十六进制转储:
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
除了倒数第二个值(00 vs. 0c)外,基础PIDLS也是二进制相同的。我现在不知道它们为什么与众不同,或者我能怎么解决这个问题?
问题
最佳答案
这些确实是不同的 shell 对象。您可以使用SIGDN_NORMALDISPLAY选项将获得的PIDL传递给SHGetNameFromIDList(),以将它们转换为可读的字符串。长的PIDL(带有0x0c)将转换为“所有控制面板项目”,短的PIDL将转换为“控制面板”。
通过使用SHGetSpecialFolderLocation()检索控制面板控件的虚拟文件夹开始了此问题。与“控制面板”对象区别于桌面根目录。我认为您需要通过获取控制面板的PIDL来解决此问题,并忽略虚拟文件夹。一种方法是使用ILCloneFirst将虚拟文件夹转换为根对象:
PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);
或者,您可以对控制面板CLSID“:: {26EE0668-A00A-44D7-9371-BEB064C98683}”进行硬编码,然后使用SHParseDisplayName()将其转换为PIDL。