Initialisieren von Shellerweiterungshandlern

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

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

  • DllMain. Der Standardeinstiegspunkt zur 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 Klassenfactory implementieren. 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-and-Drop-Handler
  • Eigenschaftenblatthandler

Die folgenden Themen werden im weiteren Verlauf dieses Themas behandelt:

Implementieren von IPersistFile

Die IPersistFile-Schnittstelle ist so konzipiert, dass ein Objekt aus einer Datenträgerdatei geladen oder in dieser gespeichert werden kann. Es verfügt über sechs Methoden zusätzlich zu IUnknown, fünf eigene methoden und die GetClassID-Methode , die es von IPersist erbt. Bei Shell-Erweiterungen wird IPersist nur verwendet, um ein Shell-Erweiterungshandlerobjekt zu initialisieren. Da in der Regel keine Lese- oder Schreibvorgänge auf dem Datenträger erforderlich sind, erfordern nur die Methoden GetClassID und Load eine Implementierung ohne Token.

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 die Shell gerade arbeitet. Der zweite ist dwMode, der den Dateizugriffsmodus angibt. Da normalerweise kein Zugriff auf Dateien erforderlich ist, ist dwMode in der Regel null. Die -Methode speichert diese Werte nach Bedarf für einen späteren Verweis.

Das folgende Codefragment veranschaulicht, wie ein typischer Shell-Erweiterungshandler 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 IUnknown nur über eine Methode, IShellExtInit::Initialize. Die -Methode verfügt über drei Parameter, die die Shell verwenden kann, um verschiedene Arten von Informationen zu übergeben. 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 nicht standardmäßigen Drag-and-Drop-Handlern ist dies die PIDL des Zielordners.
  • pDataObject enthält einen Zeiger auf die IDataObject-Schnittstelle eines Datenobjekts. Das Datenobjekt enthält einen oder mehrere Dateinamen in 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 bei 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;
}

Infotip-Anpassung

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 mit bestimmten 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 im 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 semikolontrennte Liste kanonischer Eigenschaftsnamen oder {fmtid}-Pid-Paare fest, wobei propname ein kanonischer Eigenschaftenname und {fmtid}, pid ein FMTID/PID-Paar ist.

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 Zusammenfassung des Themas PIDSI_SUBJECT
Kommentar Dokumentkommentare PIDSI_COMMENT - oder Ordner-/Laufwerkeigenschaften
PageCount Anzahl von Seiten PIDSI_PAGECOUNT
Name Angezeigter Name Standardordneransicht
OriginalLocation Speicherort der Ursprünglichen Datei Aktenkofferordner und Papierkorbordner
DateDeleted Datum des Löschens der Datei Ordner "Papierkorb"
type Dateityp Standardansicht für Ordnerdetails
Size Größe der Datei Standardansicht für Ordnerdetails
SyncCopyIn Identisch mit OriginalLocation Identisch mit OriginalLocation
Geändert Datum der letzten Änderung Standardansicht für Ordnerdetails
Erstellt Erstellungsdatum Standardansicht für Ordnerdetails
Zugegriffen Datum des letzten Zugriffs Standardansicht für Ordnerdetails
InFolder Verzeichnis mit der Datei Dokumentsuchergebnisse
Rang Qualität der Suchabfrage Dokumentsuchergebnisse
FreeSpace Verfügbarer Speicherplatz Laufwerke
NumberOfVisits Anzahl von Aufrufen Ordner "Favoriten"
Attribute Dateiattribute Standardansicht für Ordnerdetails
Company Unternehmensname PIDDSI_COMPANY
Category Dokumentkategorie PIDDSI_CATEGORY
Copyright Medienrecht PIDMSI_COPYRIGHT
HTMLInfoTipFile HTML InfoTip-Datei Desktop.ini Datei für Ordner

 

Registrieren von Shellerweiterungshandlern