Initialisieren von Shellerweiterungshandlern

Ein Großteil der Implementierung eines Shell-Erweiterungshandlerobjekts wird durch seinen Typ vorgegeben. Es gibt jedoch einige allgemeine Elemente. In diesem Thema werden die Aspekte der Implementierung erläutert, die von allen Shellerweiterungshandlern gemeinsam genutzt werden.

Alle Shellerweiterungshandler sind COM-Objekte (In-Process Component Object Model). Ihnen muss eine GUID zugewiesen und registriert werden, wie unter Registrieren von Shellerweiterungshandlernbeschrieben. Sie werden als DLLs implementiert und müssen die folgenden Standardfunktionen exportieren:

  • DllMain. Der Standardeinstiegspunkt für die DLL.
  • DllGetClassObject. Macht die Klassenfactory des Objekts verfügbar.
  • DllCanUnloadNow. COM ruft diese Funktion auf, um zu bestimmen, ob das Objekt Clients bedient. Andernfalls kann das System die DLL entladen und den zugeordneten Arbeitsspeicher freigeben.

Wie alle COM-Objekte müssen Shellerweiterungshandler eine IUnknown-Schnittstelle und eine Klassenfactoryimplementieren. Die meisten müssen auch eine IPersistFile- oder IShellExtInit-Schnittstelle in Windows XP oder früher implementieren. Diese wurden in Windows Vista durch IInitializeWithStream, IInitializeWithItem und IInitializeWithFile ersetzt. Die Shell verwendet diese Schnittstellen, um den Handler zu initialisieren.

Die IPersistFile-Schnittstelle muss wie folgt implementiert werden:

  • Symbolhandler
  • Datenhandler
  • Löschen von Handlern

Die IShellExtInit-Schnittstelle muss wie folgt implementiert werden:

  • Kontextmenühandler
  • Drag & Drop-Handler
  • Eigenschaftenblatthandler

Die folgenden Themen werden im weiteren Verlauf dieses Themas erläutert:

Implementieren von IPersistFile

Die IPersistFile-Schnittstelle ist so konzipiert, dass ein Objekt aus einer Datenträgerdatei geladen oder darin gespeichert werden kann. Es verfügt über sechs Methoden zusätzlich zu IUnknown,fünf eigene Methoden und die GetClassID-Methode, die sie von IPersisterbt. Bei Shell-Erweiterungen wird IPersist nur zum Initialisieren eines Shell-Erweiterungshandlerobjekts verwendet. Da in der Regel kein Lese- oder Schreibzugriff auf den Datenträger erforderlich ist, erfordern nur die Methoden GetClassID und Load eine Nichttokenimplementierungen.

Die Shell ruft zuerst GetClassID auf, und die Funktion gibt den Klassenbezeichner (CLSID) des Erweiterungshandlerobjekts zurück. Die Shell ruft dann Load auf und übergibt zwei Werte. Die erste , pszFile, ist eine Unicode-Zeichenfolge mit dem Namen der Datei oder des Ordners, für die Shell ausgeführt werden soll. Der zweite ist dwMode, der den Dateizugriffsmodus angibt. Da normalerweise kein Zugriff auf Dateien erforderlich ist, ist dwMode in der Regel 0 (null). Die -Methode speichert diese Werte nach Bedarf für einen späteren Verweis.

Das folgende Codefragment veranschaulicht, wie ein typischer Shellerweiterungshandler die Methoden GetClassID und Load implementiert. Es ist für die Verarbeitung von ANSI oder Unicode konzipiert. CLSID _ SampleExtHandler ist die GUID des Erweiterungshandlerobjekts, und CSampleShellExtension ist der Name der Klasse, die zum Implementieren der -Schnittstelle verwendet wird. Die Variablen m _ szFileName und m _ dwMode sind private Variablen, die zum Speichern des Dateinamens und der Zugriffsflags verwendet werden.

class CSampleShellExtension : public IPersistFile
{
    // Method declarations not included

    private:
    WCHAR m_szFileName[MAX_PATH];    // The file name
    DWORD m_dwMode;                  // The file access mode
}

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
    *pCLSID = CLSID_SampleExtHandler;
}

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
    m_dwMode = dwMode;
    return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile); 
}

// The implementation sample is continued in the next section.

Implementieren von IShellExtInit

Die IShellExtInit-Schnittstelle verfügt zusätzlich zu IUnknownnur über eine Methode, IShellExtInit::Initialize. Die -Methode verfügt über drei Parameter, mit denen die Shell verschiedene Informationstypen übergeben kann. Die übergebenen Werte hängen vom Typ des Handlers ab, und einige können auf NULL festgelegt werden.

  • pidlFolder enthält den Zeiger eines Ordners auf eine Elementbezeichnerliste (PIDL). Dies ist eine absolute PIDL. Bei Eigenschaftenblatterweiterungen ist dieser Wert NULL. Bei Kontextmenüerweiterungen ist es die PIDL des Ordners, der das Element enthält, dessen Kontextmenü angezeigt wird. Bei Drag & Drop-Handlern, die keine Standardmäßige sind, ist dies die PIDL des Zielordners.
  • pDataObject enthält einen Zeiger auf die IDataObject-Schnittstelle eines Datenobjekts. Das Datenobjekt enthält mindestens einen Dateinamen im CF _ HDROP-Format.
  • hRegKey enthält einen Registrierungsschlüssel für das Dateiobjekt oder den Ordnertyp.

Die IShellExtInit::Initialize-Methode speichert den Dateinamen, den IDataObject-Zeiger und den Registrierungsschlüssel nach Bedarf für die spätere Verwendung. Das folgende Codefragment veranschaulicht eine Implementierung von IShellExtInit::Initialize. Der Einfachheit halber wird in diesem Beispiel davon ausgegangen, dass das Datenobjekt nur eine einzelne Datei enthält. Im Allgemeinen kann das Datenobjekt mehrere Dateien enthalten, von denen jede extrahiert werden muss.

// This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.

class CSampleShellExtension : public IShellExtInit
{
    // Method declarations not included
    
    private:
    // IDList of the folder for extensions invoked on the folder, such as 
    // background context menu handlers or nondefault drag-and-drop handlers. 
    PIDLIST_ABSOLUTE m_pidlFolder;
    
    // The data object contains an expression of the items that the handler is 
    // being initialized for. Use SHCreateShellItemArrayFromDataObject to 
    // convert this object to an array of items. Use SHGetItemFromObject if you
    // are only interested in a single Shell item. If you need a file system
    // path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
    IDataObject *m_pdtobj;
    
    // For context menu handlers, the registry key provides access to verb 
    // instance data that might be stored there. This is a rare feature to use 
    // so most extensions do not need this variable.
    HKEY m_hRegKey;             
}
    
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.

IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder,
                                                 __in_opt IDataObject *pDataObject, 
                                                 __in_opt HKEY hRegKey) 
{ 
    // In some cases, handlers are initialized multiple times. Therefore, 
    // clear any previous state here.
    CoTaskMemFree(m_pidlFolder);
    m_pidlFolder = NULL;
    
    if (m_pdtobj)
    { 
        m_pdtobj->Release(); 
    }
    
    if (m_hRegKey)
    {
        RegCloseKey(m_hRegKey);
        m_hRegKey = NULL;
    }
    
    // Capture the inputs for use later.
    HRESULT hr = S_OK;
    
    if (pidlFolder)
    {
        m_pidlFolder = ILClone(pidlFolder);   // Make a copy to use later.
        hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
    }
    
    if (SUCCEEDED(hr))
    {
        // If a data object pointer was passed into the method, save it and
        // extract the file name. 
        if (pDataObject) 
        { 
            m_pdtobj = pDataObject; 
            m_pdtobj->AddRef(); 
        }
    
        // It is uncommon to use the registry handle, but if you need it,
        // duplicate it now.
        if (hRegKey)
        {
            LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey); 
            hr = HRESULT_FROM_WIN32(result);
        }
    }
    
    return hr;
}

Anpassung von Infotips

Es gibt zwei Möglichkeiten, Infotips anzupassen. Eine Möglichkeit besteht darin, ein Objekt zu implementieren, das IQueryInfo unterstützt, und dann das Objekt unter dem richtigen Unterschlüssel in der Registrierung zu registrieren (siehe unten). Alternativ können Sie entweder eine feste Zeichenfolge oder eine Liste bestimmter Dateieigenschaften angeben, die angezeigt werden sollen.

Um eine feste Zeichenfolge für eine Namespaceerweiterung anzuzeigen, erstellen Sie unter dem CLSID-Schlüssel Ihrer Namespaceerweiterung einen Unterschlüssel namens InfoTip. Legen Sie die Daten dieses Unterschlüssels auf die Zeichenfolge fest, die angezeigt werden soll.

HKEY_CLASSES_ROOT
   CLSID
      {CLSID}
         InfoTip = InfoTip string for your namespace extension

Um eine feste Zeichenfolge für einen Dateityp anzuzeigen, erstellen Sie unter dem ProgID-Schlüssel des Dateityps, für den Sie Infotips bereitstellen möchten, einen Unterschlüssel namens InfoTip. Legen Sie die Daten dieses Unterschlüssels auf die Zeichenfolge fest, die angezeigt werden soll.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = InfoTip string for all files of this type

Wenn die Shell bestimmte Dateieigenschaften in der Infotip für einen bestimmten Dateityp anzeigen soll, erstellen Sie unter dem ProgID-Schlüssel dieses Dateityps einen Unterschlüssel namens InfoTip. Legen Sie die Daten dieses Unterschlüssels als eine durch Semikolons getrennten Liste kanonischer Eigenschaftennamen oder {fmtid}, pid-Paare fest, wobei propname ein kanonischer Eigenschaftenname und {fmtid}, pid ein FMTID/PID-Paarist.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = propname;propname;{fmtid},pid;{fmtid},pid

Die folgenden Eigenschaftennamen können verwendet werden.

Eigenschaftenname BESCHREIBUNG Abgerufen von
Autor Autor des Dokuments PIDSI _ AUTHOR
Titel Titel des Dokuments PIDSI _ TITLE
Subject Betreffzusammenfassung PIDSI _ SUBJECT
Kommentar Dokumentkommentare PIDSI _ COMMENT- oder Ordner-/Laufwerkeigenschaften
PageCount Anzahl von Seiten PIDSI _ PAGECOUNT
Name Anzeigename Standardordneransicht
OriginalLocation Speicherort der ursprünglichen Datei Ordner "Kleinbuchstaben" und Papierkorb Ordner
DateDeleted Datum, an dem die Datei gelöscht wurde Papierkorb Ordner
type Dateityp Standardansicht der Ordnerdetails
Size Größe der Datei Standardansicht der Ordnerdetails
SyncCopyIn Identisch mit OriginalLocation Identisch mit OriginalLocation
Geändert Datum der letzten Änderung Standardansicht der Ordnerdetails
Erstellt Erstellungsdatum Standardansicht der Ordnerdetails
Zugegriffen Datum des letzten Zugriffes Standardansicht der Ordnerdetails
InFolder Verzeichnis, das die Datei enthält Dokumentsuchergebnisse
Rang Qualität der Such übereinstimmung Dokumentsuchergebnisse
FreeSpace Verfügbarer Speicherplatz Laufwerke
NumberOfVisits Anzahl von Aufrufen Ordner "Favoriten"
Attributes Dateiattribute Standardansicht der Ordnerdetails
Company Unternehmensname PIDDSI _ COMPANY
Category Dokumentkategorie PIDDSI _ CATEGORY
Copyright Medienrechte PIDMSI _ COPYRIGHT
HTMLInfoTipFile HTML-InfoTip-Datei Desktop.ini-Datei für den Ordner

Registrieren von Shellerweiterungshandlern