2009-11-19 52 views
7

如果我有一個IShellFolder接口指針。我怎樣才能獲得PIDL?如何獲取IShellFolder的PIDL

我可以看到如何枚舉它的孩子,我可以看到如何使用它來比較任何兩個孩子。但是我怎麼能得到它自己的pidl?

我問,因爲我想知道:

這是的IShellFolder ==另一個的IShellFolder

我可以使用IShellFolder::CompareIDs(),但我必須有兩個文件夾的ID。

回答

6

我發現你可以查詢一個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; 
}; 
1

Mordachai的答案可能是正確的,但對我這個查詢使得在兩條戰線上沒有意義:

  1. 我不相信有一個發佈的文件說IShellFolder只能有一個父親。對於任何特定的shell文件夾可能有多種方式。控制面板可通過「我的電腦」,通過「開始」菜單訪問,並在文件系統中的任意位置創建一個連接點。看起來shell小組的oringinal意圖是,在給定一個IShellFolder實例的情況下,對於外部用戶什麼碰巧是無關緊要的。

  2. 另外,實例化IShellFolder 的任何應用程序肯定是這樣做是通過了解PIDL的知識。如果你的應用程序關心到一個IShellFolder的路徑,它已經擁有這些信息。你是怎麼解開它的? (何必外殼團隊添加一個方法來幫助應用程序跟蹤自己的數據?)

+0

1.是的,但文件系統是shell空間中大多數對象的基本事實。雖然它可能有多個鏈接,路口等到給定的文件夾,但只能有一個實際的父文件夾。它的定義是文件系統。這一直是如此,並有SHBindToParent來證實這一事實。 2.並非如此。可以直接從SHGetDesktopFolder實例化一個IShellFolder。無論如何,通常系統設計只能走一條最終失敗的路。從一個轉換到另一個的能力更加靈活和強大。 – Mordachai 2009-11-23 16:08:49

+0

1.那麼如果某些文件系統有限制呢。shell命名空間是爲了表達更一般的情況而設計的。 2.謝謝指出1個特例。非常聰明。 – 2009-11-23 17:42:46

6

無論是克里斯·莫迪凱或對#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都可以設置許多其他的文件夾。

4

我忘了提及SHGetIDListFromObject函數。

它只適用於Windows Vista及更高版本。它有記錄的優點,雖然簡單。當然,您可以從my own documentation獲得更多細節。這表明Microsoft知道了另外兩種獲取指向shell命名空間中對象的任意接口指針的PIDL的方法。

+0

感謝您的鏈接和細節。我不記得是否偶然發現了這個功能,但我僅限於維持XP兼容性(儘管聽起來我可以使用動態鏈接到shell32.dll)。 – Mordachai 2010-11-23 21:51:51