Implementieren der grundlegenden Ordnerobjektschnittstellen
Das Verfahren zum Implementieren einer Namespaceerweiterung ähnelt dem Verfahren für alle anderen IN-Process-Component Object Model(COM)-Objekts. Alle Erweiterungen müssen drei primäre Schnittstellen unterstützen, die Windows Explorer die 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 komplexere Features unterstützen, z. B. Kontextmenüs oder Drag & Drop, und eine Ordneransicht bereitstellen.
In diesem Dokument wird erläutert, wie die primären und optionalen Schnittstellen implementiert werden, Windows Explorer aufruft, um Informationen zum Inhalt der Erweiterung zu erhalten. Eine Erörterung der Implementierung einer Ordneransicht und der Anpassung des Windows-Explorers finden Sie unter Implementieren einer Ordneransicht.
- Grundlegende Implementierung und Registrierung
- Behandeln von PIDLs
- Implementieren der primären Schnittstellen
- Implementieren der optionalen Schnittstellen
- Arbeiten mit der Standardimplementierung der Shellordneransicht
Grundlegende Implementierung und Registrierung
Als In-Process-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. Weitere Informationen finden Sie in der COM-Dokumentation.
Registrieren einer Erweiterung
Wie bei allen COM-Objekten müssen Sie eine Klassenbezeichner-GUID (CLSID) 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 Verbindungspunkten. Diese Werte gelten nicht für Erweiterungen, deren Verbindungspunkte Dateisystemordner sind. Weitere Informationen finden Sie unter Angeben des Speicherorts einer Namespaceerweiterung. Um das Verhalten einer Erweiterung mit einem virtuellen Verbindungspunkt zu ändern, fügen Sie mindestens einen der folgenden Werte zum CLSID-Schlüssel der Erweiterung hinzu:
- WantsFORPARSING. Der Analysename für eine Erweiterung mit einem virtuellen Verbindungspunkt hat normalerweise die Form ::{GUID}. Erweiterungen dieses Typs enthalten normalerweise virtuelle Elemente. Einige Erweiterungen, z. B. Eigene Dokumente, entsprechen jedoch dateisystemordnern, obwohl sie über virtuelle Verbindungspunkte verfügen. Wenn ihre Erweiterung Dateisystemobjekte auf diese Weise darstellt, können Sie den WantsFORPARSING-Wert festlegen. Windows Der Explorer fordert dann den Analysenamen Ihres Stammordners an, indem er die IShellFolder::GetDisplayNameOf-Methode des Ordnerobjekts aufruft, bei der uFlags auf SLKDN _ FORPARSING und pidl auf einen einzelnen leeren Zeiger auf eine Elementbezeichnerliste (PIDL) festgelegt sind. Eine leere PIDL enthält nur ein Abschlusszeichen. Ihre Methode sollte dann den Analysenamen ::{GUID} des Stammordners zurückgeben.
- HideFolderVerbs. Die verben, die unter HKEY _ CLASSES _ ROOT Folder registriert \ sind, 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 HideFolderVerbs-Wert fest.
- HideAsDelete. Wenn ein Benutzer versucht, ihre Erweiterung zu löschen, blendet Windows Explorer die Erweiterung aus.
- HideAsDeletePerUser. Dieser Wert hat die gleiche Auswirkung wie HideAsDelete, jedoch pro Benutzer. Die Erweiterung ist nur für die 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 haben kann. Das Ordnerobjekt muss die IShellIconOverlay-Schnittstelle unterstützen. Bevor Windows Explorer das Symbol des Stammordners anzeigt, fordert er ein Überlagerungssymbol an, indem er eine der beiden IShellIconOverlay-Methoden aufruft, bei denen pidlItem auf eine leere PIDL festgelegt ist.
Die verbleibenden Werte und Unterschlüssel gelten für alle Erweiterungen:
- Um den Anzeigenamen des Verbindungspunktordners der Erweiterung anzugeben, legen Sie den Standardwert des CLSID-Unterschlüssels der Erweiterung auf eine entsprechende Zeichenfolge fest.
- Wenn der Cursor auf einen Ordner zeigt, wird in der Regel eine Infotip angezeigt, die den Inhalt des Ordners beschreibt. 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 eine Infotip-Datei für den Stammordner Ihrer Erweiterung bereitstellen zu können.
- 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 und dem Index des Symbols in dieser Datei.
- Standardmäßig enthält das Kontextmenü des Stammordners Ihrer Erweiterung die unter HKEY CLASSES ROOT Folder definierten _ _ \ 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 weitere Elemente hinzufügen oder vorhandene Elemente überschreiben, ähnlich wie bei einem Dateityp. 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, um das Kontextmenü des Stammordners zu verarbeiten, können Sie einen Kontextmenühandler implementieren. Um den Kontextmenühandler zu registrieren, erstellen Sie eine ShellEx-Taste unter dem CLSID-Schlüssel der Erweiterung. Registrieren Sie die CLSID des Handlers wie für einen herkömmlichen Creating Shell Extension Handlers.
- Um dem Eigenschaftenblatt Eigenschaften des Stammordners eine Seite hinzuzufügen, geben Sie dem Ordner das SFGAO _ HASPROPSHEET-Attribut, 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 für einen herkömmlichen Creating Shell Extension Handlers.
- Um die Attribute des Stammordners anzugeben, fügen Sie dem CLSID-Unterschlüssel der Erweiterung einen ShellFolder-Unterschlüssel hinzu. Erstellen Sie einen Attributwert, und legen Sie ihn auf die entsprechende Kombination von SFGAO _ XXX-Flags fest.
In der folgenden Tabelle sind einige häufig verwendete Attribute für Stammordner aufgeführt.
| Flag | Wert | BESCHREIBUNG |
|---|---|---|
| SFGAO-ORDNER _ | 0x20000000 | Der Stammordner der Erweiterung enthält ein oder mehrere Elemente. |
| SFGAO _ HASSUBFOLDER | 0x80000000 | Der Stammordner der Erweiterung enthält einen oder mehrere Unterordner. Windows Der Explorer platzieren 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 unter einem der virtuellen Ordner platziert werden. |
| SFGAO _ CANRENAME | 0x00000010 | Der Stammordner der Erweiterung kann vom Benutzer umbenannt werden. Das Kontextmenü des Ordners enthält das Element Umbenennen. |
| SFGAO _ HASPROPSHEET | 0x00000040 | Der Stammordner der Erweiterung verfügt über ein Eigenschaftenblatt. Das Kontextmenü des Ordners enthält das Element Eigenschaften. Um das Eigenschaftenblatt bereitstellen zu können, 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 Shellnamespace muss über eine eindeutige PIDL verfügen. Windows Der Explorer weist Ihrem Stammordner eine PIDL zu und übergibt den Wert während der Initialisierung an Die Erweiterung. Ihre Erweiterung ist dann dafür verantwortlich, jedem ihrer Objekte eine ordnungsgemäß konstruierte PIDL zu zuweisen und diese PIDLs auf Anforderung Windows Explorer zur Verfügung zu stellen. 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 all diese Aufgaben zu verarbeiten.
Der Begriff PIDL ist abhängig vom Kontext für eine ITEMIDLIST-Struktur oder einen Zeiger auf eine solche Struktur. Wie deklariert, verfügt eine ITEMIDLIST-Struktur über einen einzelnen Member, 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 auf die gleiche Weise 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, bei der der cb-Member auf NULL festgelegt ist. Das Abschlusszeichen ist erforderlich, da die Anzahl der SHITEMID-Strukturen in der PIDL eines Objekts vom Speicherort des Objekts im Shellnamespace und vom 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, ihre Größe oder sogar die Gesamtzahl der SHITEMID-Strukturen zu bestimmen. Stattdessen müssen Sie das gepackte Array strukturstrukturiieren, bis Sie das Abschlusszeichen erreichen.
Um eine PIDL zu erstellen, muss Ihre Anwendung:
- Erstellen Sie eine SHITEMID-Struktur für jedes ihrer Objekte.
- Stellen Sie die relevanten SHITEMID-Strukturen in einer PIDL zusammen.
Erstellen einer SHITEMID-Struktur
Die SHITEMID-Struktur eines Objekts identifiziert das Objekt innerhalb seines Ordners eindeutig. Tatsächlich besteht ein von vielen IShellFolder-Methoden verwendeter PIDL-Typ nur aus der SHITEMID-Struktur des Objekts, gefolgt von einem Abschlusszeichen. Die Definition einer SHITEMID-Struktur ist:
typedef struct _SHITEMID {
USHORT cb;
BYTE abID[1];
} SHITEMID, * LPSHITEMID;
Der abID-Member ist der Bezeichner des Objekts. Da die Länge von abID nicht definiert ist und variieren kann, wird das cb-Member auf die Größe der SHITEMID-Struktur in Bytes festgelegt.
Da weder die Länge noch der Inhalt von abID standardisiert sind, können Sie ein beliebiges Schema verwenden, das AbID-Werte Ihren Objekten zuweisen soll. Die einzige Anforderung ist, dass sich zwei Objekte nicht im selben Ordner mit identischen Werten befinden dürfen. Aus Leistungsgründen sollte Ihre SHITEMID-Struktur jedoch DWORD-ausgerichtet sein. Anders ausgedrückt: Sie sollten Ihre abID-Werte so erstellen, dass cb ein integrales Vielfaches von 4 ist.
In der Regel verweist abID auf eine erweiterungsdefinierte Struktur. Zusätzlich zur Objekt-ID wird diese Struktur häufig verwendet, um eine Vielzahl verwandter Informationen zu enthalten, z. B. den Typ oder die Attribute des Objekts. Die Ordnerobjekte Ihrer Erweiterung können dann schnell die Informationen aus der PIDL extrahieren, anstatt sie abfragen zu müssen.
Hinweis
Einer der wichtigsten Aspekte beim Entwerfen einer Datenstruktur für eine PIDL besteht in der dauerhaften und transportierbaren Struktur. Im Kontext von PIDLs haben diese Begriffe folgende Bedeutung:
- Dauerhaften. Das System platziert PIDLs häufig in verschiedenen Typen von langfristigem Speicher, z. B. Verknüpfungsdateien. Diese PIDLs können 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 aussagekräftig sein. Diese Anforderung bedeutet beispielsweise, dass Sie keine Zeiger oder Handles in Ihrer PIDL-Struktur verwenden sollten. PIDLs, die diese Art von Daten enthalten, sind normalerweise bedeutungslos, wenn sie später vom System aus dem Speicher wiederhergestellt werden.
- Ortsbewegliche. Eine PIDL muss sinnvoll bleiben, wenn sie von einem Computer auf einen anderen übertragen wird. Beispielsweise kann eine PIDL in eine Verknüpfungsdatei 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 aussagekräftig sein. Um beispielsweise sicherzustellen, dass Ihre PIDLs transportierbar sind, verwenden Sie explizit ENTWEDER ANSI- oder Unicode-Zeichen. Vermeiden Sie Datentypen wie TCHAR oder LPTSTR. Wenn Sie diese Datentypen verwenden, kann eine PIDL, die auf einem Computer mit einer Unicode-Version Ihrer Erweiterung erstellt wurde, von einer ANSI-Version dieser Erweiterung, die auf einem anderen Computer ausgeführt wird, nicht gelesen werden.
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. Dieser Member macht MYPIDLDATA zu einer gültigen SHITEMID-Struktur für sich selbst. Die restlichen Member entsprechen dem abID-Member einer SHITEMID-Struktur und halten private Daten. Der dwType-Member ist ein erweiterungsdefinierter Wert, der den Typ des Objekts angibt. In diesem Beispiel wird dwType für Ordner auf TRUE und andernfalls FALSE festgelegt. Mit diesem Member können Sie beispielsweise schnell bestimmen, ob das Objekt ein Ordner ist oder nicht. Der wszDisplayName-Member enthält den Anzeigenamen des Objekts. Da Sie zwei verschiedenen Objekten im gleichen 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 zu gewährleisten, dass die SHITEMID-Struktur DWORD-ausgerichtet ist. Um die Größe Ihrer PIDLs zu begrenzen, können Sie stattdessen ein Zeichenarray variabler Länge verwenden und den Wert von cb entsprechend anpassen. Pad the display string with enough ' \ 0' characters to maintain the structure es DWORD alignment. Andere Member, die in der Struktur nützlich sein können, sind die Größe des Objekts, Attribute oder der Analysename.
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 mit einer einzelnen 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. Diese Art von PIDL beginnt am 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 innerhalb des gesamten Shell-Namespace eindeutig.
Die einfachste Möglichkeit zum Erstellen einer PIDL ist die direkte Arbeit mit der ITEMIDLIST-Struktur selbst. Erstellen Sie eine ITEMIDLIST-Struktur, weisen Sie jedoch genügend Arbeitsspeicher zu, um alle SHITEMID-Strukturen zu speichern. Die Adresse dieser Struktur wird auf die anfängliche SHITEMID-Struktur verweisen. Definieren Sie Werte für die Member dieser anfänglichen Struktur, und fügen Sie dann so viele zusätzliche SHITEMID-Strukturen wie benötigt in der richtigen Reihenfolge an. Im folgenden Verfahren wird beschrieben, wie Sie eine PIDL auf einer ebene erstellen. Sie enthält zwei SHITEMID-Strukturen– eine MYPIDLDATA-Struktur gefolgt von einem Abschlusszeichen:
- Verwenden Sie die CoTaskMemAlloc-Funktion, um Speicher für die PIDL zu reservieren. Ordnen Sie genügend Arbeitsspeicher für Ihre privaten Daten sowie einen USHORT (zwei Bytes) für das Abschlusszeichen zu. Cast the result to LPMYPIDLDATA.
- Legen Sie den cb-Member 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 variabler Länge verwenden möchten, müssen Sie den Wert von cb berechnen.
- Weisen Sie den privaten Datenmitgliedern entsprechende Werte zu.
- Berechnen Sie die Adresse der nächsten SHITEMID-Struktur. Cast the address of the current MYPIDLDATA structure to LPBYTE, and add that value to the value of cb determined in step 3.
- In diesem Fall ist die nächste SHITEMID-Struktur das Abschlusszeichen. Legen Sie den cb-Member der -Struktur auf 0 (null) fest.
Ordnen Sie für längere 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 den Anzeigenamen eines Objekts und gibt die PIDL auf einer einzelnen Ebene des Objekts zurück. Die Funktion geht davon aus, dass der Anzeigename, einschließlich des beendenden NULL-Zeichens, die Anzahl der Zeichen, die für die MYPIDLDATA-Struktur deklariert sind, nicht überschreitet. Wenn sich diese Annahme als fehlerhaft herausstellt, wird der Anzeigename von der StringCbCopyW-Funktion abgeschnitten. Die g _ pMalloc-Variable ist ein IMalloc-Zeiger, der an anderer Stelle erstellt und in einer globalen Variablen gespeichert wird.
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 empfängt eine vollqualifizierte PIDL für Ihren Stammordner, wenn die Shell IPersistFolder::Initializeaufruft. 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 sie benötigen, um Sie aus dem Stammordner an das Objekt zu bringen.
Interpretieren von PIDLs
Wenn die Shell oder eine Anwendung eine der Schnittstellen Ihrer Erweiterung aufruft, um Informationen zu einem Objekt anzufordern, wird das Objekt in der Regel durch eine PIDL identifiziert. 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 welches Ihrer Objekte pidl verweist.
Was die Zuordnung 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 sich außerhalb Ihrer Erweiterung im Shellnamespace befinden. Sie haben keine Möglichkeit, die Bedeutung des abID-Members dieser Strukturen zu interpretieren. Ihre Erweiterung muss die Liste der SHITEMID-Strukturen "durchgehen", bis Sie die Struktur erreichen, die Ihrem Stammordner entspricht. Von da an wissen Sie, wie Sie die Informationen in den SHITEMID-Strukturen interpretieren.
Wenn Sie die PIDL durchgehen möchten, verwenden 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 erweitern. Anschließend verweist er auf den cb-Member dieser Struktur, den Sie verwenden können, um den Zeiger auf den Anfang der nächsten SHITEMID-Struktur zu setzen usw. Überprüfen Sie bei jedem Vorwärtslauf des Zeigers die SHITEMID-Struktur, um zu ermitteln, ob Sie den Stamm des Namespace Ihrer Erweiterung erreicht haben.
Implementieren der primären Schnittstellen
Wie bei allen COM-Objekten geht es bei der Implementierung einer Erweiterung größtenteils um die Implementierung einer Auflistung von Schnittstellen. In diesem Abschnitt werden die drei primären Schnittstellen erläutert, die von allen Erweiterungen implementiert werden müssen. Sie werden für die Initialisierung und zur Bereitstellung Windows Explorers mit grundlegenden Informationen zum Inhalt der Erweiterung verwendet. Diese Schnittstellen sowie eine Ordneransichtsind alle für eine Funktionale Erweiterung erforderlich. Um jedoch die Features von Windows Explorer vollständig zu nutzen, 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. Store diese PIDL zur späteren Verwendung. Beispielsweise 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.
Normalerweise wird ein Ordnerobjekt mit der IShellFolder::BindToObject-Methode des übergeordneten Ordners erstellt und initialisiert. Wenn ein Benutzer jedoch ihre Erweiterung durchsucht, erstellt Windows Explorer das Stammordnerobjekt der Erweiterung und initialisiert es. Die PIDL, die das Stammordnerobjekt über IPersistFolder::Initialize empfängt, enthält den Pfad vom Desktop zum Stammordner, den Sie benötigen, um vollqualifizierte PIDLs für Ihre Erweiterung zu erstellen.
IShellFolder-Schnittstelle
Die Shell behandelt eine Erweiterung als hierarchisch sortierte Auflistung von Ordnerobjekten. Die IShellFolder-Schnittstelle ist der Kern jeder Erweiterungsimplementierungen. Es stellt ein Ordnerobjekt dar und stellt Windows Explorer mit vielen Informationen bereit, die zum Anzeigen des Ordnerinhalts 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 von erforderlichen und optionalen Schnittstellen verwendet, um Informationen zum Inhalt des Ordners abzurufen, ruft er über IShellFolder Zeiger auf diese Schnittstellen ab.
Windows Explorer ruft die CLSID des Stammordners Ihrer Erweiterung auf verschiedene Weise ab. Weitere Informationen finden Sie unter Angeben des Speicherorts einer Namespaceerweiterung oder Anzeigen einer Self-Contained Ansicht einer Namespaceerweiterung. Windows Der Explorer verwendet diese CLSID dann, um eine Instanz des Stammordners zu erstellen und zu initialisieren und eine IShellFolder-Schnittstelle abzufragen. 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 aufzählen kann.
- Rufen Sie verschiedene Arten von Informationen zum 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 wie Symbolen oder Kontextmenüs abgefragt werden.
- Fordern Sie ein Ordnerobjekt an, das einen Unterordner des Stammordners darstellt.
Wenn ein Benutzer einen Unterordner des Stammordners öffnet, ruft Windows Explorer IShellFolder::BindToObjectauf. Ihre Erweiterung erstellt und initialisiert ein neues Ordnerobjekt, das den Unterordner darstellt, und gibt die zugehörige IShellFolder-Schnittstelle zurück. Windows Der Explorer ruft diese Schnittstelle dann für verschiedene Informationstypen auf usw., bis der Benutzer entscheidet, an anderer Stelle im Shellnamespace 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 durch Aufrufen der IShellFolder::EnumObjects-Methode bestimmen, was der Ordner enthält. Diese Methode erstellt ein OLE-Standardenumerationsobjekt, das eine IEnumIDList-Schnittstelle verfügbar macht und diesen Schnittstellenzeiger zurückgibt. Die IEnumIDList-Schnittstelle ermöglicht Windows Explorer das Abrufen der PIDLs aller im Ordner enthaltenen Objekte. 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 wie IContextMenufür den Ordner selbst anzufordern. 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::GetUIObjectOfaufgerufen.
GetUIObjectOf
Obwohl grundlegende Informationen zum Inhalt eines Ordners über die IShellFolder-Methoden verfügbar sind, kann Ihre Erweiterung auch Windows Explorer mit verschiedenen Arten von zusätzlichen Informationen bereitstellen. Beispielsweise 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 zu versuchen, zusätzliche Informationen zu einem Objekt abzurufen, das in einem Ordner enthalten ist. Windows Der Explorer gibt an, für welches Objekt die Informationen und die IID der relevanten Schnittstelle benötigt werden. Das Ordnerobjekt erstellt dann ein -Objekt, das die angeforderte Schnittstelle verfügbar macht und den Schnittstellenzeiger zurückgibt.
If your extension allows users to transfer objects with drag-and-drop or the clipboard, Windows Explorer will call IShellFolder::GetUIObjectOf to request an IDataObject or IDropTarget interface. For details, see Transferring Shell Objects with Drag-and-Drop and the Clipboard.
Windows Der Explorer ruft IShellFolder::CreateViewObject auf, wenn die gleiche Art von Informationen zum Ordner selbst gewünscht wird.
BindToObject
Windows Der 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 ist. 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 enthalten, die nicht NULL ist. Da es mehrere Möglichkeiten gibt, Objekte zu benennen, gibt Windows Explorer den Typ des Namens an, indem mindestens ein S MSIDNF-Flag im uFlags-Parameter festgelegt wird. Einer von zwei Werten, SWSDN _ NORMAL oder SWSDN _ INFOLDER, wird festgelegt, um anzugeben, ob der Name relativ zum Ordner oder relativ zum Desktop sein soll. Einer der anderen drei Werte, SAHDN _ FOREDITING, SAHDN _ FORADDRESSBAR oder SAHDN _ 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 SAHDN _ FOREDITING, SAHDN _ FORADDRESSBAR und SAHDN _ FORPARSING nicht festgelegt sind, geben Sie den Anzeigenamen des Objekts zurück. Wenn das SWSDN _ FORPARSING-Flag festgelegt ist, fordert Windows Explorer einen Analysenamen an. Analysenamen werden an IShellFolder::P arseDisplayName übergeben, um die PIDL eines Objekts abzurufen, obwohl sie sich möglicherweise auf einer oder mehreren Ebenen unter dem aktuellen Ordner in der Namespacehierarchie befindet. Beispielsweise ist der Analysename eines Dateisystemobjekts sein Pfad. Sie können den vollqualifizierten Pfad jedes Objekts im Dateisystem an die IShellFolder::P arseDisplayName-Methode des Desktops übergeben und die vollqualifizierte PIDL des Objekts zurückgeben.
Beim Analysieren 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. Beispielsweise sind viele der virtuellen Shellordner 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 "Roundtrips" zu machen. Wenn z. B. ein Aufrufer einen Analysenamen an IShellFolder::P arseDisplayName übergibt, um die PIDL eines Objekts abzurufen, und diese PIDL dann an IShellFolder::GetDisplayNameOf übergibt, wenn das SLKDN _ FORPARSING-Flag festgelegt ist, sollte der Aufrufer den ursprünglichen Analysenamen wiederherstellen.
GetAttributesOf
Windows Der Explorer ruft die IShellFolder::GetAttributesOf-Methode auf, um die Attribute eines oder mehrere Elemente zu bestimmen, die in einem Ordnerobjekt enthalten sind. Der Wert von cidl gibt die Anzahl der Elemente in der Abfrage an, und aPidl zeigt auf eine Liste ihrer PIDLs.
Da das Testen einiger Attribute zeitaufwändig sein kann, schränkt Windows Explorer die Abfrage in der Regel auf eine Teilmenge der verfügbaren Flags ein, indem deren Werte in rfgInOut festlegen. 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 werden, damit ein Element ordnungsgemäß angezeigt wird. Wenn ein Element beispielsweise ein Ordner ist, der Unterordner enthält, müssen Sie das SFGAO _ HASSUBFOLDER-Flag festlegen. Andernfalls Windows Explorer in der Strukturansicht kein + neben dem Symbol des Elements angezeigt.
ParseDisplayName
Die IShellFolder::P arseDisplayName-Methode ist in gewissem Sinne ein Spiegelbild von IShellFolder::GetDisplayNameOf. Diese Methode wird am häufigsten verwendet, um 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 vollqualifiziert. Anders ausgedrückt: Obwohl die PIDL mehrere SHITEMID-Strukturen enthalten kann, ist die erste entweder der 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 an fordern. Da die Ermittlung aller anwendbaren Attribute zeitaufwändig sein kann, wird der Aufrufer nur die SFGAO _ XXX-Flags festlegen, die Informationen darstellen, an denen der Aufrufer interessiert ist. Sie sollten bestimmen, welches dieser Attribute für das Objekt true ist, und die verbleibenden Flags löschen.
IEnumIDList-Schnittstelle
Wenn Windows Explorer die in einem Ordner enthaltenen Objekte aufzählen muss, ruft er IShellFolder::EnumObjects auf. Das Ordnerobjekt muss ein Enumerationsobjekt erstellen, das die IEnumIDList-Schnittstelle verfügbar macht, und diesen Schnittstellenzeiger zurückgeben. Windows Der Explorer verwendet dann in der Regel IEnumIDList, um die PIDLs aller im Ordner enthaltenen Objekte aufzählen.
IEnumIDList ist eine STANDARDMÄßIGE OLE-Enumerationsschnittstelle und wird wie gewohnt implementiert. Denken Sie jedoch daran, dass die von Ihnen zurückkommenden 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 davon, z. B. IExtractIcon,ermöglichen es Ihnen, verschiedene Aspekte der Ansicht Ihrer Erweiterung durch den Benutzer anzupassen. Others, such as IDataObject, allow your extension to support features such as drag-and-drop.
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 an fordern:
- Windows Der Explorer ruft den IShellFolder::GetUIObjectOf eines Ordnerobjekts auf, um eine Schnittstelle für eines der im Ordner enthaltenen Objekte an fordern.
- Windows Der Explorer ruft den IShellFolder::CreateViewObject eines Ordnerobjekts auf, um eine Schnittstelle für den Ordner selbst an fordern.
Um die Informationen zur Verfügung zu stellen, erstellt das Ordnerobjekt ein Objekt, das die angeforderte Schnittstelle verfügbar macht und den Schnittstellenzeiger zurückgibt. Windows Der Explorer ruft dann diese Schnittstelle auf, 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. Mit der -Schnittstelle kann ihre Erweiterung benutzerdefinierte Symbole für die Objekte angeben, die im Ordner enthalten sind. Andernfalls werden die Standardsymbole für Dateien und Ordner verwendet. Erstellen Sie zum Bereitstellen eines benutzerdefinierten Symbols ein Symbolextraktionsobjekt, das IExtractIcon verfügbar macht, und geben Sie einen Zeiger auf diese Schnittstelle zurück. Weitere Informationen finden Sie in der IExtractIcon-Referenzdokumentation oder unter Erstellen von Symbolhandlern.
IContextMenu
Wenn ein Benutzer mit der rechten Maustaste auf ein Objekt klickt, Windows Explorer eine IContextMenu-Schnittstelle an. Um Kontextmenüs für Ihre Objekte zur Verfügung zu stellen, erstellen Sie ein Menühandlerobjekt und geben 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, IContextMenu2oder IContextMenu3.
IQueryInfo
Windows Der Explorer ruft die IQueryInfo-Schnittstelle auf, um eine Infotip-Textzeichenfolge abzurufen.
IDataObject und IDropTarget
Wenn Ihre Objekte vom Windows-Explorer angezeigt werden, kann ein Ordnerobjekt nicht direkt wissen, wann ein Benutzer versucht, ein Objekt ausschneiden, zu kopieren oder zu ziehen. Stattdessen fordert Windows Explorer eine IDataObject-Schnittstelle an. Damit das Objekt übertragen werden kann, erstellen Sie ein Datenobjekt und geben einen Zeiger auf seine IDataObject-Schnittstelle zurück.
Auf ähnliche Weise versucht ein Benutzer möglicherweise, ein Datenobjekt in einer Windows Explorer-Darstellung eines Ihrer Objekte zu ablegen, z. B. ein Symbol oder einen Adressleistenpfad. Windows Der Explorer fordert dann eine IDropTarget-Schnittstelle an. Damit das Datenobjekt gelöscht werden kann, erstellen Sie ein Objekt, das eine IDropTarget-Schnittstelle verfügbar macht, und geben Sie den Schnittstellenzeiger zurück.
Die Verarbeitung der Datenübertragung ist einer der schwierigeren Aspekte beim Schreiben von Namespaceerweiterungen. For a detailed discussion, see Transferring Shell Objects with Drag-and-Drop and the Clipboard.
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.