2009-11-19 6 views
7

Wenn ich einen IShellFolder Schnittstellenzeiger habe. Wie kann ich seine PIDL erhalten?So erhalten Sie die PIDL eines IShellFolder

Ich kann sehen, wie man seine Kinder aufzählt, und ich kann sehen, wie man es benutzt, um irgendwelche zwei Kinder zu vergleichen. Aber wie könnte ich ein eigenes Pidl bekommen?

Ich frage, weil ich wissen möchte:

diese IShellFolder Ist == Ein weiterer IShellFolder

ich IShellFolder::CompareIDs() verwenden können, aber ich habe die IDs der beiden Ordner haben.

Antwort

6

Ich habe festgestellt, dass Sie eine IShellFolder für IPersistFolder2 abfragen können, die GetCurFolder() hat, die ihre absolute PIDL zurückgibt. Ich könnte dann einfach den IShellFolder für den Desktop zu CompareIDs() verwenden, um festzustellen, ob sie gleich sind. Ich habe die Umrisse gefunden, während ich auf SHGetIDListFromObject schaute. Ich könnte diese Funktion nicht einfach benutzen, weil Vista, und ich brauche XP-Kompatibilität.

Hier ist eine Skizze, wie es funktioniert (vorausgesetzt, Sie eine ifolder_desktop haben, und ifolder_other, die Zeiger IShellFolder sind PIDL ist ein einfacher Helfer, die IDLISTs werden ausgeplant richtig stellt sicher, dass.):

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); 

Bei jemand interessiert sich für meine einfache PIDL Klasse:

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 Antwort könnte richtig sein, aber mir diese Abfrage macht keinen Sinn, an zwei Fronten:

  1. Ich glaube nicht, dass es ein veröffentlichtes Dokument gibt, das besagt, dass ein IShellFolder nur einen Elternteil haben kann. Es gibt möglicherweise mehrere Möglichkeiten für einen bestimmten Shell-Ordner. Auf das Bedienfeld kann über Arbeitsplatz, über das Startmenü und überall im Dateisystem zugegriffen werden, indem Sie einen Verbindungspunkt zu ihm erstellen. Es scheint, dass die Shell-Teams oringinale Absicht war, angesichts einer IShellFolder-Instanz, sollte es keine externen Benutzer was seine zufällige Lage passiert sein.

  2. Plus, jede Anwendung, die einen IShellFolder sicherlich instanziiert von einem Wissen über eine PIDL. Wenn Ihre App sich um den Pfad zu einem IShellFolder gekümmert hat, hat sie diese Informationen bereits HADEN. Wie hast du es verloren? (Und warum sollte das Shell-Team eine Methode hinzufügen Anwendungen zu helfen, den Überblick über ihre eigenen Daten behalten?)

+0

1. True, aber das Dateisystem ist die zugrunde liegende Wahrheit für die meisten Objekte im Shell-Raum. Und obwohl es möglich ist, mehrere Links, Junctions usw. zu einem bestimmten Ordner zu haben, kann es nur einen tatsächlichen übergeordneten Ordner geben. Es ist definitionsgemäß das Dateisystem. Das war schon immer so, und es gibt SHBindToParent, der diese Wahrheit bestätigt. 2. Nicht so. Man kann einen IShellFolder direkt aus SHGetDesktopFolder erstellen. Auf jeden Fall ist es oft Systeme entworfen, die nur einen Weg gehen können, die letztlich scheitern. Die Fähigkeit, von einem zum anderen zu konvertieren, ist flexibler und robuster. – Mordachai

+0

1. Also, wenn einige Dateisysteme Grenzen haben. Der Shell-Namespace wurde entworfen, um den allgemeineren Fall auszudrücken. 2. Danke für den Hinweis auf den 1 Sonderfall. Sehr schlau. –

6

Was entweder Chris oder Mordechai auf # schreibt 1 ist ohnehin nicht auf den Punkt. Die Frage bezieht sich nicht auf Objekte im Shell-Namespace, sondern auf Objekte mit einer IShellFolder-Schnittstelle. Der Besitz einer IShellFolder-Schnittstelle bedeutet nicht, dass eine Präsenz im Shell-Namespace vorhanden ist. Die ursprüngliche Frage ist schlecht formuliert, da angenommen wird, dass ein Objekt mit einer IShellFolder-Schnittstelle "eine eigene PIDL" haben muss.

Das Beste, was Sie tun können, denke ich, ist, wie Mordechai vorschlägt: Sehen Sie, ob das Objekt auch eine IPersistFolder2-Schnittstelle hat. Der Zweck dieser Schnittstelle besteht darin, das Objekt im Shell-Namespace zu fixieren, wodurch der Ordner persistent wird. Ziehen Sie nicht aus dem Fehlen veröffentlichter Dokumentation den Blick auf das, was Microsoft tatsächlich über die IPersistFolder- und IPersistFolder2-Schnittstellen und die Methoden Initialize und GetCurFolder sagt.Vor allem: "Sie müssen diese Schnittstelle implementieren, damit die ITEMIDLIST des Shell-Ordnerobjekts abgerufen werden kann."

Auf # 2, ich fürchte, Chris ist definitiv nicht korrekt. Ein IShellFolder kann sicherlich ohne PIDL erhalten werden. Die Systemsteuerung, die Chris für # 1 einführte, bietet ein einfaches Gegenbeispiel für # 2. Füttern Sie einfach CLSID_ControlPanel und IIS_IShellFolder zu CoCreateInstance. Sie erhalten eine perfekt nutzbare Instanziierung der Systemsteuerung, ohne jemals "eine PIDL zu kennen". Es gibt eine Handvoll anderer Shell-Ordner, die in SHELL32 implementiert werden können, und jede DLL kann eine beliebige Anzahl anderer erstellen.

4

Ich habe vergessen, die SHGetIDListFromObject Funktion zu erwähnen.

Es ist nur in Windows Vista und höher verfügbar. Es hat den Vorteil, dokumentiert zu sein, wenn auch knapp. Sie erhalten natürlich weitere Details von my own documentation. Dies zeigt, dass Microsoft zwei weitere Möglichkeiten zum Abrufen eines PIDL für einen beliebigen Schnittstellenzeiger auf ein Objekt im Shell-Namespace kennt.

+0

Danke für den Link & Details. Ich kann mich nicht erinnern, ob ich auf diese Funktion gestoßen bin, aber ich bin darauf beschränkt, die XP-Kompatibilität aufrechtzuerhalten (obwohl es so klingt, als hätte ich eine dynamische Verbindung zu shell32.dll verwenden können). – Mordachai