如果我有一個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