我看到应该做 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 也是二进制相同的。我目前不知道为什么它们不同,或者我能做些什么来解决这个问题?!
问题
- 是否有另一种方法以不包含看似虚假的额外空字节的方式获取控件的 PIDL?
- 或者,是否有更好的方法来获取枚举项的 PIDL(CMFCShellTreeCtrol 获取绝对 PIDL 的方式是否存在不足,以至于无法包含最后的空字节?)
- 有没有办法获取控制面板作为相对 PIDL,然后将其与相对枚举 PIDL(我也有)进行比较?
- ???
最佳答案
这些确实是不同的 shell 对象。您可以使用 SIGDN_NORMALDISPLAY 选项将获得的 PIDL 传递给 SHGetNameFromIDList() 以将它们转换为可读字符串。长 PIDL(带 0x0c)转换为“所有控制面板项”,短 PIDL 转换为“控制面板”。
这个问题是从使用 SHGetSpecialFolderLocation() 检索控制面板控件的虚拟文件夹开始的。不同于桌面根目录下的控制面板对象。我认为您需要通过获取控制面板的 PIDL 并忽略虚拟文件夹来解决此问题。一种方法是使用 ILCloneFirst 将虚拟文件夹转换为根对象:
PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);
或者您可以对控制面板 CLSID 进行硬编码,“::{26EE0668-A00A-44D7-9371-BEB064C98683}”,然后使用 SHParseDisplayName() 将其转换为 PIDL。
关于c++ - 为什么控制面板的 PIDL 会有所不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14325953/