Implementieren der Grundlegenden Ordnerobjektschnittstellen

Die Prozedur zum Implementieren einer Namespaceerweiterung ähnelt der für jedes andere com-Objekt (Component Object Model) des Prozesses. Alle Erweiterungen müssen drei primäre Schnittstellen unterstützen, die Windows-Explorer mit den grundlegenden Informationen bereitstellen, die zum Anzeigen der Ordner der Erweiterung in der Strukturansicht erforderlich sind. Um jedoch die Funktionen von Windows Explorer vollständig nutzen zu können, muss Ihre Erweiterung auch eine oder mehrere optionale Schnittstellen verfügbar machen, die anspruchsvollere Features unterstützen, z. B. Kontextmenüs oder Drag-and-Drop, und eine Ordneransicht bereitstellen.

In diesem Dokument wird erläutert, wie Sie die primären und optionalen Schnittstellen implementieren, die Windows Explorer aufruft, um Informationen über den Inhalt Ihrer Erweiterung zu erhalten. Eine Erläuterung zum Implementieren einer Ordneransicht und zum Anpassen von Windows Explorer finden Sie unter Implementieren einer Ordneransicht.

Grundlegende Implementierung und Registrierung

Als prozessinterner COM-Server muss Ihre DLL mehrere Standardfunktionen und Schnittstellen verfügbar machen:

Diese Funktionen und Schnittstellen werden auf die gleiche Weise implementiert wie für die meisten anderen COM-Objekte. Ausführliche Informationen finden Sie in der COM-Dokumentation.

Registrieren einer Erweiterung

Wie bei allen COM-Objekten müssen Sie eine CLSID-GUID (Class Identifier) für Ihre Erweiterung erstellen. Registrieren Sie das Objekt, indem Sie einen Unterschlüssel von HKEY_CLASSES_ROOT\CLSID mit dem Namen für die CLSID Ihrer Erweiterung erstellen. Die DLL sollte als Prozessserver registriert werden und das Apartmentthreadingmodell angeben. Sie können das Verhalten des Stammordners einer Erweiterung anpassen, indem Sie dem CLSID-Schlüssel der Erweiterung eine Vielzahl von Unterschlüsseln und Werten hinzufügen.

Einige dieser Werte gelten nur für Erweiterungen mit virtuellen Anschlusspunkten. Diese Werte gelten nicht für Erweiterungen, deren Knotenpunkte Dateisystemordner sind. Weitere Informationen finden Sie unter Angeben des Speicherorts einer Namespaceerweiterung. Um das Verhalten einer Erweiterung mit einem virtuellen Knotenpunkt zu ändern, fügen Sie dem CLSID-Schlüssel der Erweiterung mindestens einen der folgenden Werte hinzu:

  • WantsFORPARSING. Der Analysename für eine Erweiterung mit einem virtuellen Knotenpunkt hat normalerweise das Format ::{GUID}. Erweiterungen dieses Typs enthalten normalerweise virtuelle Elemente. Einige Erweiterungen, z. B. Meine Dokumente, entsprechen jedoch tatsächlich Dateisystemordnern, obwohl sie virtuelle Knotenpunkte haben. Wenn Ihre Erweiterung Dateisystemobjekte auf diese Weise darstellt, können Sie den WantsFORPARSING-Wert festlegen. Windows Explorer fordert dann den Analysenamen Ihres Stammordners an, indem die IShellFolder::GetDisplayNameOf-Methode des Ordnerobjekts aufgerufen wird, wobei uFlags auf SHGDN_FORPARSING festgelegt ist und pidl auf einen einzelnen leeren Zeiger auf eine Elementbezeichnerliste (PIDL) festgelegt ist. Eine leere PIDL enthält nur einen Abschluss. Ihre Methode sollte dann den ::{GUID}-Analysenamen des Stammordners zurückgeben.
  • HideFolderVerbs. Die unter HKEY_CLASSES_ROOT\Ordner registrierten Verben sind normalerweise allen Erweiterungen zugeordnet. Sie werden im Kontextmenü der Erweiterung angezeigt und können von ShellExecute aufgerufen werden. Um zu verhindern, dass eines dieser Verben Ihrer Erweiterung zugeordnet wird, legen Sie den Wert HideFolderVerbs fest.
  • HideAsDelete. Wenn ein Benutzer versucht, Ihre Erweiterung zu löschen, blendet Windows Explorer stattdessen die Erweiterung aus.
  • HideAsDeletePerUser. Dieser Wert hat die gleiche Auswirkung wie HideAsDelete, jedoch auf Benutzerbasis. Die Erweiterung wird nur für benutzer ausgeblendet, die versucht haben, sie zu löschen. Die Erweiterung ist für alle anderen Benutzer sichtbar.
  • QueryForOverlay. Legen Sie diesen Wert fest, um anzugeben, dass das Symbol des Stammordners eine Symbolüberlagerung aufweisen kann. Das Ordnerobjekt muss die IShellIconOverlay-Schnittstelle unterstützen. Bevor Windows Explorer das Symbol des Stammordners anzeigt, fordert es ein Overlaysymbol an, indem eine der beiden IShellIconOverlay-Methoden aufgerufen wird, wobei pidlItem auf eine leere PIDL festgelegt ist.

Die restlichen Werte und Unterschlüssel gelten für alle Erweiterungen:

  • Um den Anzeigenamen des Knotenpunktordners der Erweiterung anzugeben, legen Sie den Standardwert des CLSID-Unterschlüssels der Erweiterung auf eine entsprechende Zeichenfolge fest.
  • Wenn der Cursor über einen Ordner bewegt wird, wird in der Regel eine Infoinfo angezeigt, die den Inhalt des Ordners beschreibt. Um eine Infoinfo für den Stammordner Ihrer Erweiterung bereitzustellen, erstellen Sie einen InfoTip-REG_SZ Wert für den CLSID-Schlüssel der Erweiterung, und legen Sie ihn auf eine entsprechende Zeichenfolge fest.
  • Um ein benutzerdefiniertes Symbol für den Stammordner Ihrer Erweiterung anzugeben, erstellen Sie einen Unterschlüssel des CLSID-Unterschlüssels der Erweiterung mit dem Namen DefaultIcon. Legen Sie den Standardwert von DefaultIcon auf einen REG_SZ Wert fest, der den Namen der Datei enthält, die das Symbol enthält, gefolgt von einem Komma, gefolgt von einem Minuszeichen, gefolgt vom Index des Symbols in dieser Datei.
  • Standardmäßig enthält das Kontextmenü des Stammordners Ihrer Erweiterung die unter HKEY_CLASSES_ROOT\Folderdefinierten Elemente. Die Elemente Löschen, Umbenennen und Eigenschaften werden hinzugefügt, wenn Sie die entsprechenden SFGAO_XXX-Flags festgelegt haben. Sie können dem Kontextmenü des Stammordners andere Elemente hinzufügen oder vorhandene Elemente wie bei einem Dateityp überschreiben. Erstellen Sie einen Shell-Unterschlüssel unter dem CLSID-Schlüssel der Erweiterung, und definieren Sie Befehle, wie unter Erweitern von Kontextmenüs erläutert.
  • Wenn Sie eine flexiblere Möglichkeit benötigen, das Kontextmenü des Stammordners zu verarbeiten, können Sie einen Kontextmenühandler implementieren. Um den Kontextmenühandler zu registrieren, erstellen Sie einen ShellEx-Schlüssel unter der CLSID-Taste der Erweiterung. Registrieren Sie die CLSID des Handlers wie bei einem herkömmlichen Erstellen von Shellerweiterungshandlern.
  • Um dem Eigenschaftenblatt Eigenschaften des Stammordners eine Seite hinzuzufügen, weisen Sie dem Ordner das attribut SFGAO_HASPROPSHEET zu, und implementieren Sie einen Eigenschaftenblatthandler. Um den Eigenschaftenblatthandler zu registrieren, erstellen Sie einen ShellEx-Schlüssel unter dem CLSID-Schlüssel der Erweiterung. Registrieren Sie die CLSID des Handlers wie bei einem herkömmlichen Erstellen von Shellerweiterungshandlern.
  • Um die Attribute des Stammordners anzugeben, fügen Sie dem CLSID-Unterschlüssel der Erweiterung einen ShellFolder-Unterschlüssel hinzu. Erstellen Sie einen Attribute-Wert, und legen Sie ihn auf die entsprechende Kombination aus SFGAO_XXX Flags fest.

In der folgenden Tabelle sind einige häufig verwendete Attribute für Stammordner aufgeführt.

Flag Wert BESCHREIBUNG
SFGAO_FOLDER 0x20000000 Der Stammordner der Erweiterung enthält mindestens ein Element.
SFGAO_HASSUBFOLDER 0x80000000 Der Stammordner der Erweiterung enthält mindestens einen Unterordner. Windows Explorer platziert ein Pluszeichen ( + ) neben dem Ordnersymbol.
SFGAO_CANDELETE 0x00000020 Der Stammordner der Erweiterung kann vom Benutzer gelöscht werden. Das Kontextmenü des Ordners enthält das Element Löschen . Dieses Flag sollte für Verbindungspunkte festgelegt werden, die sich unter einem der virtuellen Ordner befinden.
SFGAO_CANRENAME 0x00000010 Der Stammordner der Erweiterung kann vom Benutzer umbenannt werden. Das Kontextmenü des Ordners enthält ein Umbenennen-Element .
SFGAO_HASPROPSHEET 0x00000040 Der Stammordner der Erweiterung verfügt über ein Eigenschaftenblatt . Das Kontextmenü des Ordners enthält ein Eigenschaftenelement . Um das Eigenschaftenblatt bereitzustellen, müssen Sie einen Eigenschaftenblatthandler implementieren. Registrieren Sie den Handler unter dem CLSID-Schlüssel der Erweiterung, wie zuvor erläutert.

 

Das folgende Beispiel zeigt den CLSID-Registrierungseintrag für eine Erweiterung mit dem Anzeigenamen MyExtension. Die Erweiterung verfügt über ein benutzerdefiniertes Symbol, das in der DLL der Erweiterung mit dem Index 1 enthalten ist. Die Attribute SFGAO_FOLDER, SFGAO_HASSUBFOLDER und SFGAO_CANDELETE werden festgelegt.

HKEY_CLASSES_ROOT
   CLSID
      {Extension CLSID}
         (Default) = MyExtension
         InfoTip = Some appropriate text
      DefaultIcon
         (Default) = c:\MyDir\MyExtension.dll,-1
      InProcServer32
         (Default) = c:\MyDir\MyExtension.dll
         ThreadingModel = Apartment
      ShellFolder
         Attributes = 0xA00000020

Behandeln von PIDLs

Jedes Element im Shell-Namespace muss über eine eindeutige PIDL verfügen. Windows Explorer weist Ihrem Stammordner eine PIDL zu und übergibt den Wert während der Initialisierung an Ihre Erweiterung. Ihre Erweiterung ist dann für das Zuweisen einer ordnungsgemäß erstellten PIDL zu jedem ihrer Objekte und die Bereitstellung dieser PIDLs für Windows Explorer auf Anforderung verantwortlich. Wenn die Shell eine PIDL verwendet, um eines der Objekte Ihrer Erweiterung zu identifizieren, muss ihre Erweiterung in der Lage sein, die PIDL zu interpretieren und das bestimmte Objekt zu identifizieren. Die Erweiterung muss jedem Objekt auch einen Anzeigenamen und einen Analysenamen zuweisen. Da PIDLs von praktisch jeder Ordnerschnittstelle verwendet werden, implementieren Erweiterungen häufig einen einzelnen PIDL-Manager , um alle diese Aufgaben zu verarbeiten.

Der Begriff PIDL ist die Abkürzung für eine ITEMIDLIST-Struktur oder einen Zeiger auf eine solche Struktur, abhängig vom Kontext. Wie deklariert, verfügt eine ITEMIDLIST-Struktur über ein einzelnes Element, eine SHITEMID-Struktur . Die ITEMIDLIST-Struktur eines Objekts ist tatsächlich ein gepacktes Array von zwei oder mehr SHITEMID-Strukturen . Die Reihenfolge dieser Strukturen definiert einen Pfad durch den Namespace, genau wie c:\MyDirectory\MyFile definiert einen Pfad durch das Dateisystem. In der Regel besteht die PIDL eines Objekts aus einer Reihe von SHITEMID-Strukturen , die den Ordnern entsprechen, die den Namespacepfad definieren, gefolgt von der SHITEMID-Struktur des Objekts, gefolgt von einem Abschlusszeichen.

Das Abschlusszeichen ist eine SHITEMID-Struktur , wobei das cb-Element auf NULL festgelegt ist. Das Abschlusszeichen ist erforderlich, da die Anzahl der SHITEMID-Strukturen in der PIDL eines Objekts von der Position des Objekts im Shell-Namespace und dem Ausgangspunkt des Pfads abhängt. Darüber hinaus kann die Größe der verschiedenen SHITEMID-Strukturen variieren. Wenn Sie eine PIDL erhalten, haben Sie keine einfache Möglichkeit, deren Größe oder sogar die Gesamtzahl der SHITEMID-Strukturen zu bestimmen. Stattdessen müssen Sie das gepackte Array Struktur für Struktur "durchlaufen", bis Sie das Abschlusszeichen erreichen.

Um eine PIDL zu erstellen, muss Ihre Anwendung Folgendes ausführen:

  1. Erstellen Sie für jedes objekt eine SHITEMID-Struktur .
  2. Stellen Sie die relevanten SHITEMID-Strukturen zu einer PIDL zusammen.

Erstellen einer SHITEMID-Struktur

Die SHITEMID-Struktur eines Objekts identifiziert das Objekt in seinem Ordner eindeutig. Tatsächlich besteht ein PIDL-Typ, der von vielen der IShellFolder-Methoden verwendet wird, nur aus der SHITEMID-Struktur des Objekts, gefolgt von einem Abschlusszeichen. Die Definition einer SHITEMID-Struktur lautet:

typedef struct _SHITEMID { 
    USHORT cb; 
    BYTE   abID[1]; 
} SHITEMID, * LPSHITEMID;

Das abID-Element ist der Bezeichner des Objekts. Da die Länge von abID nicht definiert ist und variieren kann, wird der cb-Member auf die Größe der SHITEMID-Struktur in Bytes festgelegt.

Da weder die Länge noch der Inhalt von abID standardisiert ist, können Sie jedes Schema verwenden, das Sie Ihren Objekten abID-Werte zuweisen möchten. Die einzige Voraussetzung ist, dass Sie nicht zwei Objekte mit identischen Werten im selben Ordner haben können. Aus Leistungsgründen sollte Ihre SHITEMID-Struktur jedoch DWORD-ausgerichtet sein. Anders ausgedrückt: Sie sollten Ihre abID-Werte so konstruieren, dass cb ein integrales Vielfaches von 4 ist.

In der Regel verweist abID auf eine durch die Erweiterung definierte Struktur. Zusätzlich zur OBJEKT-ID wird diese Struktur häufig verwendet, um eine Vielzahl von verwandten Informationen wie den Typ oder die Attribute des Objekts zu speichern. Die Ordnerobjekte Ihrer Erweiterung können dann schnell die Informationen aus der PIDL extrahieren, anstatt sie abzufragen.

Hinweis

Einer der wichtigsten Aspekte beim Entwerfen einer Datenstruktur für eine PIDL besteht darin, die Struktur dauerhaft und transportierbar zu machen. Im Kontext von PIDLs ist die Bedeutung dieser Begriffe:

  • Dauerhaften. Das System platziert HÄUFIG PIDLs in verschiedenen Arten von langzeitigen Speicher, z. B. Verknüpfungsdateien. Diese PIDLs können dann später aus dem Speicher wiederhergestellt werden, möglicherweise nach dem Neustart des Systems. Eine PIDL, die aus dem Speicher wiederhergestellt wurde, muss weiterhin gültig und für Ihre Erweiterung von Bedeutung sein. Diese Anforderung bedeutet für instance, dass Sie keine Zeiger oder Handles in Ihrer PIDL-Struktur verwenden sollten. PIDLs, die diese Art von Daten enthalten, sind normalerweise bedeutungslos, wenn das System sie später aus dem Speicher wiederherstellt.
  • Ortsbewegliche. Eine PIDL muss sinnvoll bleiben, wenn sie von einem Computer zu einem anderen transportiert wird. Beispielsweise kann eine PIDL in eine Tastenkombinationsdatei geschrieben, auf eine Diskette kopiert und auf einen anderen Computer übertragen werden. Diese PIDL sollte für Ihre Erweiterung, die auf dem zweiten Computer ausgeführt wird, weiterhin sinnvoll sein. Verwenden Sie für instance explizit ANSI- oder Unicode-Zeichen, um sicherzustellen, dass Ihre PIDLs transportierbar sind. Vermeiden Sie Datentypen wie TCHAR oder LPTSTR. Wenn Sie diese Datentypen verwenden, kann eine PIDL, die auf einem Computer erstellt wurde, auf dem eine Unicode-Version Ihrer Erweiterung ausgeführt wird, nicht von einer ANSI-Version dieser Erweiterung gelesen werden, die auf einem anderen Computer ausgeführt wird.

 

Die folgende Deklaration zeigt ein einfaches Beispiel für eine Datenstruktur.

typedef struct tagMYPIDLDATA {
  USHORT cb;
  DWORD dwType;
  WCHAR wszDisplayName[40];
} MYPIDLDATA, *LPMYPIDLDATA;

Das cb-Element wird auf die Größe der MYPIDLDATA-Struktur festgelegt. Dieses Element macht MYPIDLDATA zu einer gültigen SHITEMID-Struktur in und für sich. Die restlichen Member entsprechen dem abID-Member einer SHITEMID-Struktur und enthalten private Daten. Der dwType-Member ist ein durch die Erweiterung definierter Wert, der den Typ des Objekts angibt. In diesem Beispiel ist dwType für Ordner auf TRUE und andernfalls AUF FALSE festgelegt. Mit diesem Member können Sie für instance schnell bestimmen, ob es sich bei dem Objekt um einen Ordner handelt oder nicht. Das wszDisplayName-Element enthält den Anzeigenamen des Objekts. Da Sie zwei verschiedenen Objekten im selben Ordner nicht den gleichen Anzeigenamen zuweisen würden, dient der Anzeigename auch als Objekt-ID. In diesem Beispiel ist wszDisplayName auf 40 Zeichen festgelegt, um sicherzustellen, dass die SHITEMID-StrukturDWORD-ausgerichtet ist. Um die Größe Ihrer PIDLs zu begrenzen, können Sie stattdessen ein Zeichenarray mit variabler Länge verwenden und den Wert von cb entsprechend anpassen. Füllen Sie die Anzeigezeichenfolge mit genügend "\0"-Zeichen, um die DWORD-Ausrichtung der Struktur beizubehalten. Andere Member, die für das Einfügen in die -Struktur nützlich sein können, sind die Größe, die Attribute oder der Analysename des Objekts.

Erstellen einer PIDL

Nachdem Sie SHITEMID-Strukturen für Ihre Objekte definiert haben, können Sie sie verwenden, um eine PIDL zu erstellen. PIDLs können für eine Vielzahl von Zwecken erstellt werden, aber die meisten Aufgaben verwenden einen von zwei Arten von PIDL. Die einfachste, eine PIDL auf einer ebene, identifiziert das Objekt relativ zum übergeordneten Ordner. Diese Art von PIDL wird von vielen der IShellFolder-Methoden verwendet. Eine PIDL-Ebene enthält die SHITEMID-Struktur des Objekts, gefolgt von einem Abschlusszeichen. Eine vollqualifizierte PIDL definiert einen Pfad durch die Namespacehierarchie vom Desktop zum Objekt. Dieser PIDL-Typ beginnt auf dem Desktop und enthält eine SHITEMID-Struktur für jeden Ordner im Pfad, gefolgt vom -Objekt und dem Abschlusszeichen. Eine vollqualifizierte PIDL identifiziert das Objekt eindeutig im gesamten Shellnamespace.

Die einfachste Möglichkeit zum Erstellen einer PIDL besteht darin, direkt mit der ITEMIDLIST-Struktur selbst zu arbeiten. Erstellen Sie eine ITEMIDLIST-Struktur , aber weisen Sie genügend Arbeitsspeicher für alle SHITEMID-Strukturen zu. Die Adresse dieser Struktur verweist auf die anfängliche SHITEMID-Struktur . Definieren Sie Werte für die Member dieser anfänglichen Struktur, und fügen Sie dann beliebig viele zusätzliche SHITEMID-Strukturen in der entsprechenden Reihenfolge an. Im folgenden Verfahren wird beschrieben, wie Sie eine PIDL auf einer ebeneren Ebene erstellen. Sie enthält zwei SHITEMID-Strukturen – eine MYPIDLDATA-Struktur gefolgt von einem Abschlusszeichen:

  1. Verwenden Sie die Funktion CoTaskMemAlloc , um Arbeitsspeicher für die PIDL zuzuweisen. Weisen Sie genügend Arbeitsspeicher für Ihre privaten Daten sowie eine USHORT (zwei Bytes) für das Abschlusszeichen zu. Wandeln Sie das Ergebnis in LPMYPIDLDATA um.
  2. Legen Sie das cb-Element der ersten MYPIDLDATA-Struktur auf die Größe dieser Struktur fest. In diesem Beispiel würden Sie cb auf sizeof(MYPIDLDATA) festlegen. Wenn Sie eine Struktur mit variabler Länge verwenden möchten, müssen Sie den Wert von cb berechnen.
  3. Weisen Sie den privaten Datenmembern geeignete Werte zu.
  4. Berechnen Sie die Adresse der nächsten SHITEMID-Struktur . Wandeln Sie die Adresse der aktuellen MYPIDLDATA-Struktur in LPBYTE um, und fügen Sie diesen Wert dem in Schritt 3 ermittelten Wert von cb hinzu.
  5. In diesem Fall ist die nächste SHITEMID-Struktur der Abschlusszeichen. Legen Sie den cb-Member der Struktur auf 0 (null) fest.

Weisen Sie bei längeren PIDLs ausreichend Arbeitsspeicher zu, und wiederholen Sie die Schritte 3 bis 5 für jede zusätzliche SHITEMID-Struktur .

Die folgende Beispielfunktion verwendet den Typ und Anzeigenamen eines Objekts und gibt die PIDL auf einer ebene Ebene zurück. Die Funktion geht davon aus, dass der Anzeigename, einschließlich des abschließenden NULL-Zeichens , die Anzahl der Zeichen, die für die MYPIDLDATA-Struktur deklariert wurden, nicht überschreitet. Wenn sich diese Annahme als fehlerhaft erweist, schneidet die StringCbCopyW-Funktion den Anzeigenamen ab. Die g_pMalloc Variable ist ein IMalloc-Zeiger , der an anderer Stelle erstellt und in einer globalen Variablen gespeichert ist.

LPITEMIDLIST CreatePIDL(DWORD dwType, LPCWSTR pwszDisplayName)
{
    LPMYPIDLDATA   pidlOut;
    USHORT         uSize;

    pidlOut = NULL;

    //Calculate the size of the MYPIDLDATA structure.
    uSize = sizeof(MYPIDLDATA);

    // Allocate enough memory for the PIDL to hold a MYPIDLDATA structure 
    // plus the terminator
    pidlOut = (LPMYPIDLDATA)m_pMalloc->Alloc(uSize + sizeof(USHORT));

    if(pidlOut)
    {
       //Assign values to the members of the MYPIDLDATA structure
       //that is the PIDL's first SHITEMID structure
       pidlOut->cb = uSize;
       pidlOut->dwType = dwType;
       hr = StringCbCopyW(pidlOut->wszDisplayName, 
                          sizeof(pidlOut->wszDisplayName), pwszDisplayName);
       
       // TODO: Add error handling here to verify the HRESULT returned 
       // by StringCbCopyW.

       //Advance the pointer to the start of the next SHITEMID structure.
       pidlOut = (LPMYPIDLDATA)((LPBYTE)pidlOut + pidlOut->cb);

       //Create the terminating null character by setting cb to 0.
       pidlOut->cb = 0;
    }

    return pidlOut;

Eine vollqualifizierte PIDL muss über SHITEMID-Strukturen für jedes Objekt vom Desktop bis zum Objekt verfügen. Ihre Erweiterung erhält eine vollqualifizierte PIDL für Ihren Stammordner, wenn die Shell IPersistFolder::Initialize aufruft. Um eine vollqualifizierte PIDL für ein Objekt zu erstellen, verwenden Sie die PIDL, die die Shell Ihrem Stammordner zugewiesen hat, und fügen Sie die SHITEMID-Strukturen an, die erforderlich sind, um Sie aus dem Stammordner zum Objekt zu führen.

Interpretieren von PIDLs

Wenn die Shell oder eine Anwendung eine der Schnittstellen Ihrer Erweiterung aufruft, um Informationen zu einem Objekt anzufordern, identifiziert sie das Objekt in der Regel anhand einer PIDL. Einige Methoden, z. B. IShellFolder::GetUIObjectOf, verwenden PIDLs, die relativ zum übergeordneten Ordner sind und einfach zu interpretieren sind. Ihre Erweiterung erhält jedoch wahrscheinlich auch vollqualifizierte PIDLs. Ihr PIDL-Manager muss dann bestimmen, auf welche Ihrer Objekte sich PIDL bezieht.

Was die Aufgabe des Zuordnens eines Objekts zu einer vollqualifizierten PIDL erschwert, ist, dass eine oder mehrere der anfänglichen SHITEMID-Strukturen in der PIDL zu Objekten gehören können, die außerhalb Ihrer Erweiterung im Shell-Namespace liegen. Sie haben keine Möglichkeit, die Bedeutung des abID-Elements dieser Strukturen zu interpretieren. Ihre Erweiterung muss die Liste der SHITEMID-Strukturen "durchlaufen", bis Sie die Struktur erreichen, die Ihrem Stammordner entspricht. Von da an wissen Sie, wie Sie die Informationen in den SHITEMID-Strukturen interpretieren.

Um die PIDL zu durchlaufen, nehmen Sie den ersten cb-Wert , und fügen Sie ihn der Adresse der PIDL hinzu, um den Zeiger auf den Anfang der nächsten SHITEMID-Struktur zu bringen. Anschließend wird auf das cb-Element dieser Struktur gezeigt, mit dem Sie den Zeiger zum Anfang der nächsten SHITEMID-Struktur voranbringen können usw. Untersuchen Sie jedes Mal, wenn Sie den Zeiger voranbringen, die SHITEMID-Struktur , um festzustellen, ob Sie den Stamm des Namespace Ihrer Erweiterung erreicht haben.

Implementieren der primären Schnittstellen

Wie bei allen COM-Objekten ist die Implementierung einer Erweiterung im Wesentlichen eine Frage der Implementierung einer Sammlung von Schnittstellen. In diesem Abschnitt werden die drei primären Schnittstellen erläutert, die von allen Erweiterungen implementiert werden müssen. Sie werden zur Initialisierung und zur Bereitstellung grundlegender Informationen über den Inhalt der Erweiterung für Windows Explorer verwendet. Diese Schnittstellen sowie eine Ordneransicht sind alles, was für eine funktionsbezogene Erweiterung erforderlich ist. Um jedoch die Features von Windows Explorer vollständig auszunutzen, implementieren die meisten Erweiterungen auch eine oder mehrere der optionalen Schnittstellen.

IPersistFolder-Schnittstelle

Die IPersistFolder-Schnittstelle wird aufgerufen, um ein neues Ordnerobjekt zu initialisieren. Die IPersistFolder::Initialize-Methode weist dem neuen Objekt eine vollqualifizierte PIDL zu. Speichern Sie diese PIDL zur späteren Verwendung. Für instance muss ein Ordnerobjekt diese PIDL verwenden, um vollqualifizierte PIDLs für die untergeordneten Elemente des Objekts zu erstellen. Der Ersteller des Ordnerobjekts kann auch IPersist::GetClassID aufrufen, um die CLSID des Objekts anzufordern.

In der Regel wird ein Ordnerobjekt von der IShellFolder::BindToObject-Methode des übergeordneten Ordners erstellt und initialisiert. Wenn ein Benutzer jedoch ihre Erweiterung durchsucht, erstellt und initialisiert Windows Explorer das Stammordnerobjekt der Erweiterung. Die PIDL, die das Stammordnerobjekt über IPersistFolder::Initialize empfängt, enthält den Pfad vom Desktop zum Stammordner, den Sie zum Erstellen vollqualifizierter PIDLs für Ihre Erweiterung benötigen.

IShellFolder-Schnittstelle

Die Shell behandelt eine Erweiterung als hierarchisch sortierte Auflistung von Ordnerobjekten. Die IShellFolder-Schnittstelle ist der Kern jeder Erweiterungsimplementierung. Es stellt ein Ordnerobjekt dar und stellt Windows-Explorer viele der Informationen bereit, die zum Anzeigen des Inhalts des Ordners erforderlich sind.

IShellFolder ist in der Regel die einzige Ordnerschnittstelle außer IPersistFolder , die direkt von einem Ordnerobjekt verfügbar gemacht wird. Während Windows Explorer eine Vielzahl erforderlicher und optionaler Schnittstellen verwendet, um Informationen über den Inhalt des Ordners zu erhalten, werden zeiger auf diese Schnittstellen über IShellFolder abgerufen.

Windows Explorer ruft die CLSID des Stammordners Ihrer Erweiterung auf verschiedene Arten ab. Weitere Informationen finden Sie unter Angeben des Speicherorts einer Namespaceerweiterung oder Anzeigen einer Self-Contained Ansicht einer Namespaceerweiterung. Windows Explorer verwendet diese CLSID dann, um eine instance des Stammordners und der Abfrage für eine IShellFolder-Schnittstelle zu erstellen und zu initialisieren. Ihre Erweiterung erstellt ein Ordnerobjekt, das den Stammordner darstellt, und gibt die IShellFolder-Schnittstelle des Objekts zurück. Ein Großteil der restlichen Interaktion zwischen Ihrer Erweiterung und Windows Explorer erfolgt dann über IShellFolder. Windows Explorer ruft IShellFolder auf:

  • Fordern Sie ein -Objekt an, das den Inhalt des Stammordners auflisten kann.
  • Rufen Sie verschiedene Arten von Informationen über den Inhalt des Stammordners ab.
  • Fordern Sie ein Objekt an, das eine der optionalen Schnittstellen verfügbar macht. Diese Schnittstellen können dann nach zusätzlichen Informationen abgefragt werden, z. B. Symbole oder Kontextmenüs.
  • Fordern Sie ein Ordnerobjekt an, das einen Unterordner des Stammordners darstellt.

Wenn ein Benutzer einen Unterordner des Stammordners öffnet, ruft Windows Explorer IShellFolder::BindToObject auf. Ihre Erweiterung erstellt und initialisiert ein neues Ordnerobjekt, um den Unterordner darzustellen, und gibt dessen IShellFolder-Schnittstelle zurück. Windows Explorer ruft dann diese Schnittstelle für verschiedene Arten von Informationen auf, usw., bis sich der Benutzer entscheidet, an einer anderen Stelle im Shell-Namespace zu navigieren oder Windows Explorer zu schließen.

Im weiteren Verlauf dieses Abschnitts werden die wichtigeren IShellFolder-Methoden und deren Implementierung kurz erläutert.

EnumObjects

Bevor der Inhalt eines Ordners in der Strukturansicht angezeigt wird, muss Windows Explorer zunächst ermitteln, was der Ordner enthält, indem die IShellFolder::EnumObjects-Methode aufgerufen wird. Diese Methode erstellt ein OLE-Standard-Enumerationsobjekt, das eine IEnumIDList-Schnittstelle verfügbar macht und diesen Schnittstellenzeiger zurückgibt. Mit der IEnumIDList-Schnittstelle können Windows-Explorer die PIDLs aller objekte abrufen, die im Ordner enthalten sind. Diese PIDLs werden dann verwendet, um Informationen zu den im Ordner enthaltenen Objekten abzurufen. Weitere Informationen finden Sie unter IEnumIDList-Schnittstelle.

Hinweis

Die IEnumIDList::Next-Methode sollte nur PIDLs zurückgeben, die relativ zum übergeordneten Ordner sind. Die PIDL sollte nur die SHITEMID-Struktur des Objekts enthalten, gefolgt von einem Abschlusszeichen.

 

CreateViewObject

Bevor der Inhalt eines Ordners angezeigt wird, ruft Windows Explorer diese Methode auf, um einen Zeiger auf eine IShellView-Schnittstelle anzufordern. Diese Schnittstelle wird von Windows Explorer verwendet, um die Ordneransicht zu verwalten. Erstellen Sie ein Ordneransichtsobjekt, und geben Sie dessen IShellView-Schnittstelle zurück.

Die IShellFolder::CreateViewObject-Methode wird auch aufgerufen, um eine der optionalen Schnittstellen anzufordern, z. B. IContextMenu, für den Ordner selbst. Ihre Implementierung dieser Methode sollte ein -Objekt erstellen, das die angeforderte Schnittstelle verfügbar macht und den Schnittstellenzeiger zurückgibt. Wenn Windows Explorer eine optionale Schnittstelle für eines der im Ordner enthaltenen Objekte benötigt, wird IShellFolder::GetUIObjectOf aufgerufen.

GetUIObjectOf

Während grundlegende Informationen zum Inhalt eines Ordners über die IShellFolder-Methoden verfügbar sind, kann Ihre Erweiterung auch Windows-Explorer verschiedene Arten von zusätzlichen Informationen bereitstellen. Für instance können Sie Symbole für den Inhalt eines Ordners oder des Kontextmenüs eines Objekts angeben. Windows Explorer ruft die IShellFolder::GetUIObjectOf-Methode auf, um zusätzliche Informationen zu einem Objekt abzurufen, das in einem Ordner enthalten ist. Windows Explorer gibt an, für welches Objekt die Informationen und die IID der relevanten Schnittstelle benötigt werden sollen. Das Ordnerobjekt erstellt dann ein -Objekt, das die angeforderte Schnittstelle verfügbar macht und den Schnittstellenzeiger zurückgibt.

Wenn Ihre Erweiterung es Benutzern ermöglicht, Objekte mit Drag-and-Drop oder der Zwischenablage zu übertragen, ruft Windows Explorer IShellFolder::GetUIObjectOf auf, um eine IDataObject- oder IDropTarget-Schnittstelle anzufordern. Weitere Informationen finden Sie unter Übertragen von Shellobjekten mit Drag-and-Drop und der Zwischenablage.

Windows Explorer ruft IShellFolder::CreateViewObject auf, wenn dieselbe Art von Informationen über den Ordner selbst benötigt wird.

BindToObject

Windows Explorer ruft die IShellFolder::BindToObject-Methode auf, wenn ein Benutzer versucht, einen der Unterordner Ihrer Erweiterung zu öffnen. Wenn riid auf IID_IShellFolder festgelegt ist, sollten Sie ein Ordnerobjekt erstellen und initialisieren, das den Unterordner darstellt, und die IShellFolder-Schnittstelle des Objekts zurückgeben.

Hinweis

Derzeit ruft Windows Explorer diese Methode nur auf, um eine IShellFolder-Schnittstelle anzufordern. Gehen Sie jedoch nicht davon aus, dass dies immer der Fall sein wird. Sie sollten immer den Wert von riid überprüfen, bevor Sie fortfahren.

 

GetDisplayNameOf

Windows Explorer ruft die IShellFolder::GetDisplayNameOf-Methode auf, um die PIDL eines der Objekte des Ordners in einen Namen zu konvertieren. Diese PIDL muss relativ zum übergeordneten Ordner des Objekts sein. Anders ausgedrückt: Sie muss eine einzelne SHITEMID-Struktur ungleich NULL enthalten. Da es mehrere möglichkeiten gibt, Objekte zu benennen, gibt Windows Explorer den Typ des Namens an, indem mindestens ein SHGDNF-Flag im uFlags-Parameter festgelegt wird. Einer von zwei Werten, SHGDN_NORMAL oder SHGDN_INFOLDER, wird festgelegt, um anzugeben, ob der Name relativ zum Ordner oder relativ zum Desktop sein soll. Einer der anderen drei Werte, SHGDN_FOREDITING, SHGDN_FORADDRESSBAR oder SHGDN_FORPARSING, kann festgelegt werden, um anzugeben, wofür der Name verwendet wird.

Sie müssen den Namen in Form einer STRRET-Struktur zurückgeben. Wenn SHGDN_FOREDITING, SHGDN_FORADDRESSBAR und SHGDN_FORPARSING nicht festgelegt sind, geben Sie den Anzeigenamen des Objekts zurück. Wenn das SHGDN_FORPARSING-Flag festgelegt ist, fordert Windows Explorer einen Analysenamen an. Parsingnamen werden an IShellFolder::P arseDisplayName übergeben, um die PIDL eines Objekts abzurufen, obwohl es sich möglicherweise eine oder mehrere Ebenen unterhalb des aktuellen Ordners in der Namespacehierarchie befindet. Beispielsweise ist der Analysename eines Dateisystemobjekts dessen Pfad. Sie können den vollqualifizierten Pfad eines beliebigen Objekts im Dateisystem an die IShellFolder::P arseDisplayName-Methode des Desktops übergeben und die vollqualifizierte PIDL des Objekts zurückgeben.

Bei der Analyse von Namen handelt es sich zwar um Textzeichenfolgen, sie müssen jedoch nicht unbedingt den Anzeigenamen enthalten. Sie sollten Analysenamen basierend auf dem zuweisen, was am effizientesten funktioniert, wenn IShellFolder::P arseDisplayName aufgerufen wird. Für instance sind viele der virtuellen Ordner der Shell nicht Teil des Dateisystems und verfügen nicht über einen vollqualifizierten Pfad. Stattdessen wird jedem Ordner eine GUID zugewiesen, und der Analysename hat das Format ::{GUID}. Unabhängig davon, welches Schema Sie verwenden, sollte es in der Lage sein, zuverlässig "Roundtrip" zu machen. Wenn für instance ein Aufrufer einen Analysenamen an IShellFolder::P arseDisplayName übergibt, um die PIDL eines Objekts abzurufen, und dann diese PIDL an IShellFolder::GetDisplayNameOf mit festgelegtem SHGDN_FORPARSING Flag übergibt, sollte der Aufrufer den ursprünglichen Analysenamen wiederherstellen.

GetAttributesOf

Windows Explorer ruft die IShellFolder::GetAttributesOf-Methode auf, um die Attribute eines oder mehrerer Elemente zu bestimmen, die in einem Ordnerobjekt enthalten sind. Der Wert von cidl gibt die Anzahl der Elemente in der Abfrage an, und aPidl verweist auf eine Liste ihrer PIDLs.

Da das Testen für einige Attribute zeitaufwändig sein kann, beschränkt Windows Explorer die Abfrage in der Regel auf eine Teilmenge der verfügbaren Flags, indem ihre Werte in rfgInOut festgelegt werden. Ihre Methode sollte nur auf die Attribute testen, deren Flags in rfgInOut festgelegt sind. Lassen Sie die gültigen Flags festgelegt, und löschen Sie den Rest. Wenn mehr als ein Element in der Abfrage enthalten ist, legen Sie nur die Flags fest, die für alle Elemente gelten.

Hinweis

Die Attribute müssen ordnungsgemäß festgelegt sein, damit ein Element ordnungsgemäß angezeigt wird. Wenn instance ein Element ein Ordner ist, der Unterordner enthält, müssen Sie das flag SFGAO_HASSUBFOLDER festlegen. Andernfalls wird in Windows Explorer kein + neben dem Symbol des Elements in der Strukturansicht angezeigt.

 

ParseDisplayName

Die IShellFolder::P arseDisplayName-Methode ist in gewisser Weise ein Spiegel Bild von IShellFolder::GetDisplayNameOf. Die häufigste Verwendung dieser Methode besteht darin, den Analysenamen eines Objekts in die zugeordnete PIDL zu konvertieren. Der Analysename kann auf jedes Objekt verweisen, das sich unterhalb des Ordners in der Namespacehierarchie befindet. Die zurückgegebene PIDL ist relativ zum Ordnerobjekt, das die -Methode verfügbar macht, und ist in der Regel nicht voll qualifiziert. Anders ausgedrückt: Obwohl die PIDL mehrere SHITEMID-Strukturen enthalten kann, ist die erste entweder die des Objekts selbst oder der erste Unterordner im Pfad vom Ordner zum Objekt. Der Aufrufer muss diese PIDL an die vollqualifizierte PIDL des Ordners anfügen, um eine vollqualifizierte PIDL für das Objekt zu erhalten.

IShellFolder::P arseDisplayName kann auch aufgerufen werden, um die Attribute eines Objekts anzufordern. Da das Bestimmen aller anwendbaren Attribute zeitaufwändig sein kann, legt der Aufrufer nur die SFGAO_XXX Flags fest, die Informationen darstellen, an denen der Aufrufer interessiert ist. Sie sollten bestimmen, welche dieser Attribute für das Objekt wahr sind, und die verbleibenden Flags löschen.

IEnumIDList-Schnittstelle

Wenn Windows Explorer die in einem Ordner enthaltenen Objekte auflisten muss, wird IShellFolder::EnumObjects aufgerufen. Das Ordnerobjekt muss ein Enumerationsobjekt erstellen, das die IEnumIDList-Schnittstelle verfügbar macht und diesen Schnittstellenzeiger zurückgibt. Windows Explorer verwendet dann in der Regel IEnumIDList, um die PIDLs aller im Ordner enthaltenen Objekte aufzulisten.

IEnumIDList ist eine standardmäßige OLE-Enumerationsschnittstelle und wird auf die übliche Weise implementiert. Denken Sie jedoch daran, dass die zurückgegebenen PIDLs relativ zum Ordner sein müssen und nur die SHITEMID-Struktur des Objekts und ein Abschlusszeichen enthalten müssen.

Implementieren der optionalen Schnittstellen

Es gibt eine Reihe optionaler Shellschnittstellen, die von den Ordnerobjekten Ihrer Erweiterung unterstützt werden können. Viele von ihnen, z. B. IExtractIcon, ermöglichen es Ihnen, verschiedene Aspekte der Art und Weise anzupassen, wie der Benutzer Ihre Erweiterung anzeigt. Andere, z. B. IDataObject, ermöglichen es Ihrer Erweiterung, Features wie Drag-and-Drop zu unterstützen.

Keine der optionalen Schnittstellen wird direkt von einem Ordnerobjekt verfügbar gemacht. Stattdessen ruft Windows Explorer eine von zwei IShellFolder-Methoden auf, um eine Schnittstelle anzufordern:

  • Windows Explorer ruft IShellFolder::GetUIObjectOf eines Ordnerobjekts auf, um eine Schnittstelle für eines der objekte anzufordern, die im Ordner enthalten sind.
  • Windows Explorer ruft IShellFolder::CreateViewObject eines Ordnerobjekts auf, um eine Schnittstelle für den Ordner selbst anzufordern.

Um die Informationen bereitzustellen, erstellt das Ordnerobjekt ein Objekt, das die angeforderte Schnittstelle verfügbar macht und den Schnittstellenzeiger zurückgibt. Windows Explorer dann diese Schnittstelle aufrufen, um die erforderlichen Informationen abzurufen. In diesem Abschnitt werden die am häufigsten verwendeten optionalen Schnittstellen erläutert.

IExtractIcon

Windows Explorer fordert eine IExtractIcon-Schnittstelle an, bevor der Inhalt eines Ordners angezeigt wird. Die -Schnittstelle ermöglicht es Ihrer Erweiterung, benutzerdefinierte Symbole für die Objekte anzugeben, die im Ordner enthalten sind. Andernfalls werden die Standardsymbole für Datei und Ordner verwendet. Um ein benutzerdefiniertes Symbol bereitzustellen, erstellen Sie ein Symbolextraktionsobjekt, das IExtractIcon verfügbar macht und einen Zeiger auf diese Schnittstelle zurückgibt. Weitere Informationen finden Sie in der IExtractIcon-Referenzdokumentation oder erstellen von Symbolhandlern.

IContextMenu

Wenn ein Benutzer mit der rechten Maustaste auf ein Objekt klickt, fordert Windows Explorer eine IContextMenu-Schnittstelle an. Um Kontextmenüs für Ihre Objekte bereitzustellen, erstellen Sie ein Menühandlerobjekt, und geben Sie dessen IContextMenu-Schnittstelle zurück.

Die Verfahren zum Erstellen eines Menühandlerobjekts ähneln denen, die zum Erstellen einer Menühandler-Shellerweiterung verwendet werden. Weitere Informationen finden Sie unter Erstellen von Kontextmenühandlern oder in der Referenz zu IContextMenu, IContextMenu2 oder IContextMenu3 .

IQueryInfo

Windows Explorer ruft die IQueryInfo-Schnittstelle auf, um eine Infotip-Textzeichenfolge abzurufen.

IDataObject und IDropTarget

Wenn Ihre Objekte von Windows Explorer angezeigt werden, hat ein Ordnerobjekt keine direkte Möglichkeit, zu wissen, wann ein Benutzer versucht, ein Objekt zu ausschneiden, zu kopieren oder zu ziehen. Stattdessen fordert Windows Explorer eine IDataObject-Schnittstelle an. Um die Übertragung des Objekts zu ermöglichen, erstellen Sie ein Datenobjekt, und geben Sie einen Zeiger auf seine IDataObject-Schnittstelle zurück.

Ebenso kann ein Benutzer versuchen, ein Datenobjekt auf einem Windows-Explorer Darstellung eines Ihrer Objekte wie ein Symbol oder einen Adressleistenpfad zu löschen. Windows Explorer fordert dann eine IDropTarget-Schnittstelle an. Um das Verworfen des Datenobjekts zu ermöglichen, erstellen Sie ein -Objekt, das eine IDropTarget-Schnittstelle verfügbar macht und den Schnittstellenzeiger zurückgibt.

Die Behandlung der Datenübertragung ist einer der schwierigeren Aspekte beim Schreiben von Namespaceerweiterungen. Eine ausführliche Erläuterung finden Sie unter Übertragen von Shellobjekten mit Drag-and-Drop und der Zwischenablage.

Arbeiten mit der Standardimplementierung der Shellordneransicht

Datenquellen, die das Standardmäßige Shell-Ordneransichtsobjekt (DefView) verwenden, müssen diese Schnittstellen implementieren:

Optional können sie auch IPersistFolder3 implementieren.