如果我有一个IShellFolder
接口指针。我怎样才能获得PIDL?如何获取IShellFolder的PIDL
我可以看到如何枚举它的孩子,我可以看到如何使用它来比较任何两个孩子。但是我怎么能得到它自己的pidl?
我问,因为我想知道:
这是的IShellFolder ==另一个的IShellFolder
我可以使用IShellFolder::CompareIDs()
,但我必须有两个文件夹的ID。
如果我有一个IShellFolder
接口指针。我怎样才能获得PIDL?如何获取IShellFolder的PIDL
我可以看到如何枚举它的孩子,我可以看到如何使用它来比较任何两个孩子。但是我怎么能得到它自己的pidl?
我问,因为我想知道:
这是的IShellFolder ==另一个的IShellFolder
我可以使用IShellFolder::CompareIDs()
,但我必须有两个文件夹的ID。
我发现你可以查询一个IShellFolder的IPersistFolder2,它有GetCurFolder(),它返回它的绝对PIDL。然后,我可以简单地使用桌面的IShellFolder来比较ID()来确定它们是否相等。我在查看SHGetIDListFromObject时发现了这个轮廓。我不能仅仅使用该功能,因为它的Vista和我需要XP兼容性。
这里是它是如何工作的草图(假设你有一个ifolder_desktop和ifolder_other,它们的IShellFolder指针PIDL是一个简单的帮手确保IDLISTs正确释放。):
CComQIPtr<IPersistFolder2> ipf2_desktop(ifolder_desktop);
CComQIPtr<IPersistFolder2> ipf2_folder(ifolder_other);
Pidl pidl_desktop, pidl_folder;
VERIFY(SUCCEEDED(ipf2_desktop->GetCurFolder(pidl_desktop)));
VERIFY(SUCCEEDED(ipf2_folder->GetCurFolder(pidl_folder)));
HRESULT hr = ifolder_desktop->CompareIDs(NULL, pidl_desktop, pidl_folder);
pCmdUI->Enable(SUCCEEDED(hr) && HRESULT_CODE(hr) != 0);
万一任何人有兴趣在我简单的PIDL类:
class Pidl
{
public:
// create empty
Pidl() : m_pidl(NULL) { }
// create one of specified size
explicit Pidl(size_t size) : m_pidl(Pidl_Create(size)) {}
// create a copy of a given PIDL
explicit Pidl(const ITEMIDLIST * pidl) : m_pidl(Pidl_Copy(pidl)) {}
// create an absolute PIDL from a parent + child
Pidl(const ITEMIDLIST_ABSOLUTE * pParent, const ITEMIDLIST_RELATIVE * pChild) : m_pidl(Pidl_Concatenate(pParent, pChild)) { }
// return our PIDL for general use (but retain ownership of it)
operator const ITEMIDLIST *() { return m_pidl; }
// return a pointer to our pointer, for use in functions that assign to a PIDL
operator ITEMIDLIST **()
{
free();
return &m_pidl;
}
// release ownership of our PIDL
ITEMIDLIST * release()
{
ITEMIDLIST * pidl = m_pidl;
m_pidl = NULL;
return pidl;
}
void free()
{
if (m_pidl)
//Pidl_Free(m_pidl);
ILFree(m_pidl);
}
// automatically free our pidl (if we have one)
~Pidl()
{
free();
}
private:
ITEMIDLIST * m_pidl;
};
Mordachai的答案可能是正确的,但对我这个查询使得在两条战线上没有意义:
我不相信有一个发布的文件说IShellFolder只能有一个父亲。对于任何特定的shell文件夹可能有多种方式。控制面板可通过“我的电脑”,通过“开始”菜单访问,并在文件系统中的任意位置创建一个连接点。看起来shell小组的oringinal意图是,在给定一个IShellFolder实例的情况下,对于外部用户什么碰巧是无关紧要的。
另外,实例化IShellFolder 的任何应用程序肯定是这样做是通过了解PIDL的知识。如果你的应用程序关心到一个IShellFolder的路径,它已经拥有这些信息。你是怎么解开它的? (何必外壳团队添加一个方法来帮助应用程序跟踪自己的数据?)
无论是克里斯·莫迪凯或对#1写到什么是无论如何不能给点意见。这个问题不是关于shell命名空间中的对象,而是关于具有IShellFolder接口的对象。拥有一个IShellFolder接口本身并不意味着在shell命名空间中存在。原始问题不合格,因为它假定具有IShellFolder接口的对象必须具有“自己的PIDL”。
我认为最好的办法就像Mordechai所说的那样:看看对象是否也有IPersistFolder2接口。这个接口的目的是修复shell命名空间中的对象,这反过来又使文件夹保持持久性。而不是从任何缺少已发布的文档中推断,请看看微软实际上对IPersistFolder和IPersistFolder2接口以及Initialize和GetCurFolder方法的看法。最值得注意的是,“您需要实现此接口,以便可以检索Shell文件夹对象的ITEMIDLIST。”
关于#2,恐怕克里斯肯定是不正确的。一个IShellFolder当然可以在没有PIDL的情况下获得。克里斯为#1引入的控制面板为#2提供了一个准备好的反例。只需将CLSID_ControlPanel和IIS_IShellFolder提供给CoCreateInstance。您可以在没有“掌握PIDL知识”的情况下获得完全可用的控制面板实例。在SHELL32中实现了一些其他可创建的shell文件夹,并且任何DLL都可以设置许多其他的文件夹。
我忘了提及SHGetIDListFromObject
函数。
它只适用于Windows Vista及更高版本。它有记录的优点,虽然简单。当然,您可以从my own documentation获得更多细节。这表明Microsoft知道了另外两种获取指向shell命名空间中对象的任意接口指针的PIDL的方法。
感谢您的链接和细节。我不记得是否偶然发现了这个功能,但我仅限于维持XP兼容性(尽管听起来我可以使用动态链接到shell32.dll)。 – Mordachai 2010-11-23 21:51:51
1.是的,但文件系统是shell空间中大多数对象的基本事实。虽然它可能有多个链接,路口等到给定的文件夹,但只能有一个实际的父文件夹。它的定义是文件系统。这一直是如此,并有SHBindToParent来证实这一事实。 2.并非如此。可以直接从SHGetDesktopFolder实例化一个IShellFolder。无论如何,通常系统设计只能走一条最终失败的路。从一个转换到另一个的能力更加灵活和强大。 – Mordachai 2009-11-23 16:08:49
1.那么如果某些文件系统有限制呢。shell命名空间是为了表达更一般的情况而设计的。 2.谢谢指出1个特例。非常聪明。 – 2009-11-23 17:42:46