我看到应该this来比较PIDL:IShellFolder :: CompareIDs()。
特别是,我试图检测给定的绝对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与0c)之外,基础PIDLS也是二进制相同的。我现在不知道为什么他们不同,或者我能做些什么来解决这个问题?!
答案 0 :(得分:3)
这些确实是不同的shell对象。您可以使用SIGDN_NORMALDISPLAY选项将您获得的PIDL传递给SHGetNameFromIDList(),以将它们转换为可读字符串。长PIDL(带有0x0c)转换为&#34;所有控制面板项目&#34;,短的PID转换为&#34;控制面板&#34;。
通过使用SHGetSpecialFolderLocation()检索控制面板控件的虚拟文件夹,可以解决此问题。与桌面根目录下的控制面板对象不同。我认为您需要通过获取控制面板的PIDL并忽略虚拟文件夹来解决此问题。一种方法是使用ILCloneFirst将虚拟文件夹转换为根对象:
PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);
或者您可以对控制面板CLSID,&#34; :: {26EE0668-A00A-44D7-9371-BEB064C98683}&#34;进行硬编码,并使用SHParseDisplayName()将其转换为PIDL。