Freigeben über


Implementieren des COM-Objekts der Eigenschaftenseite

Eine Eigenschaftenblatterweiterung ist ein COM-Objekt, das als in-proc-Server implementiert ist. Die Eigenschaftenblatterweiterung muss die Schnittstellen IShellExtInit und IShellPropSheetExt implementieren. Eine Eigenschaftenblatterweiterung wird instanziiert, wenn der Benutzer das Eigenschaftenblatt für ein Objekt einer Klasse anzeigt, für das die Eigenschaftenblatterweiterung im Anzeigebezeichner der -Klasse registriert wurde.

Implementieren von IShellExtInit

Nachdem das COM-Objekt der Eigenschaftenblatterweiterung instanziiert wurde, wird die IShellExtInit::Initialize-Methode aufgerufen. IShellExtInit::Initialize stellt die Eigenschaftenblatterweiterung mit einem IDataObject-Objekt bereit, das Daten enthält, die sich auf das Verzeichnisobjekt beziehen, das auf dem Eigenschaftenblatt angewendet wird.

Das IDataObject enthält Daten im CFSTR_DSOBJECTNAMES Format. Das CFSTR_DSOBJECTNAMES Datenformat ist ein HGLOBAL , das eine DSOBJECTNAMES-Struktur enthält. Die DSOBJECTNAMES-Struktur enthält Verzeichnisobjektdaten, die von der Eigenschaftenblatterweiterung angewendet werden.

Das IDataObject enthält auch Daten im CFSTR_DS_DISPLAY_SPEC_OPTIONS-Format . Das CFSTR_DS_DISPLAY_SPEC_OPTIONS Datenformat ist ein HGLOBAL , das eine DSDISPLAYSPECOPTIONS-Struktur enthält. DSDISPLAYSPECOPTIONS enthält Konfigurationsdaten zur Verwendung durch die Erweiterung.

Wenn ein anderer Wert als S_OK von IShellExtInit::Initialize zurückgegeben wird, wird das Eigenschaftenblatt nicht angezeigt.

Die Parameter pidlFolder und hkeyProgID der IShellExtInit::Initialize-Methode werden nicht verwendet.

Der IDataObject-Zeiger kann durch die Erweiterung gespeichert werden, indem die Verweisanzahl des IDataObject inkrementiert wird. Diese Schnittstelle muss freigegeben werden, wenn sie nicht mehr benötigt wird.

Implementieren von IShellPropSheetExt

Nachdem IShellExtInit::Initialize zurückgegeben wurde, wird die IShellPropSheetExt::AddPages-Methode aufgerufen. Die Eigenschaftenblatterweiterung muss die Seite bzw. die Seiten während dieser Methode hinzufügen. Eine Eigenschaftenseite wird erstellt, indem eine PROPSHEETPAGE-Struktur ausgefüllt und dann an die CreatePropertySheetPage-Funktion übergeben wird. Die Eigenschaftenseite wird dann dem Eigenschaftenblatt hinzugefügt, indem die Rückruffunktion aufgerufen wird, die im lpfnAddPage-Parameter an IShellPropSheetExt::AddPages übergeben wird.

Wenn ein anderer Wert als S_OK von IShellPropSheetExt::AddPages zurückgegeben wird, wird das Eigenschaftenblatt nicht angezeigt.

Wenn die Eigenschaftenblatterweiterung zum Hinzufügen von Seiten zum Eigenschaftenblatt nicht erforderlich ist, sollte sie nicht die Rückruffunktion aufrufen, die im lpfnAddPage-Parameter an IShellPropSheetExt::AddPages übergeben wurde.

Die IShellPropSheetExt::ReplacePage-Methode wird nicht verwendet.

Übergeben des Erweiterungsobjekts an die Eigenschaftenseite

Das Eigenschaftenblatterweiterungsobjekt ist unabhängig von der Eigenschaftenseite. In vielen Fällen ist es wünschenswert, das Erweiterungsobjekt oder ein anderes Objekt von der Eigenschaftenseite aus verwenden zu können. Legen Sie hierzu das lParam-Element der PROPSHEETPAGE-Struktur auf den Objektzeiger fest. Die Eigenschaftenseite kann diesen Wert dann abrufen, wenn sie die WM_INITDIALOG-Nachricht verarbeitet. Bei einer Eigenschaftenseite ist der lParam-Parameter der WM_INITDIALOG Nachricht ein Zeiger auf die PROPSHEETPAGE-Struktur . Rufen Sie den Objektzeiger ab, indem Sie den lParam der WM_INITDIALOG Nachricht in einen PROPSHEETPAGE-Zeiger umwandeln und dann das lParam-Element der PROPSHEETPAGE-Struktur abrufen.

Das folgende C++-Codebeispiel zeigt, wie ein Objekt an eine Eigenschaftenseite übergeben wird.

case WM_INITDIALOG:
    {
        LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;

        if(NULL != pPage)
        {
            CPropSheetExt *pPropSheetExt;
            pPropSheetExt = (CPropSheetExt*)pPage->lParam;

            if(pPropSheetExt)
            {
                return pPropSheetExt>OnInitDialog(wParam, lParam);
            }
        }
    }
    break;

Beachten Sie, dass nach dem Aufruf von IShellPropSheetExt::AddPages das Eigenschaftenblatterweiterungsobjekt freigegeben und nie wieder verwendet wird. Dies bedeutet, dass das Erweiterungsobjekt gelöscht wird, bevor die Eigenschaftenseite angezeigt wird. Wenn die Seite versucht, auf den Objektzeiger zuzugreifen, wurde der Arbeitsspeicher freigegeben, und der Zeiger ist ungültig. Um dies zu korrigieren, erhöhen Sie die Verweisanzahl für das Erweiterungsobjekt, wenn die Seite hinzugefügt wird, und lassen Sie das Objekt dann los, wenn das Eigenschaftenseitendialogfeld zerstört wird. Dadurch entsteht ein weiteres Problem, da das Dialogfeld Eigenschaftenseite erst erstellt wird, wenn die Seite zum ersten Mal angezeigt wird. Wenn der Benutzer die Erweiterungsseite nie auswählt, wird die Seite nie erstellt und zerstört. Dies führt dazu, dass das Erweiterungsobjekt nie freigegeben wird, sodass ein Speicherverlust auftritt. Um dies zu vermeiden, implementieren Sie eine Rückruffunktion für Eigenschaftenseiten. Fügen Sie dazu dem dwFlags-Member der PROPSHEETPAGE-Struktur das Flag PSP_USECALLBACK hinzu, und legen Sie das pfnCallback-Element der PROPSHEETPAGE-Struktur auf die Adresse der implementierten PropSheetPageProc-Funktion fest. Wenn die PropSheetPageProc-Funktion die PSPCB_RELEASE Benachrichtigung empfängt, enthält der ppsp-Parameter des PropSheetPageProc einen Zeiger auf die PROPSHEETPAGE-Struktur . Das lParam-Element der PROPSHEETPAGE-Struktur enthält den Erweiterungszeiger, der zum Freigeben des Objekts verwendet werden kann.

Das folgende C++-Codebeispiel zeigt, wie ein Erweiterungsobjekt freigegeben wird.

UINT CALLBACK CPropSheetExt::PageCallbackProc(  HWND hWnd,
                                                UINT uMsg,
                                                LPPROPSHEETPAGE ppsp)
{
    switch(uMsg)
    {
    case PSPCB_CREATE:
        // Must return TRUE to enable the page to be created.
        return TRUE;

    case PSPCB_RELEASE:
        {
            /*
            Release the object. This is called even if the page dialog box was 
            never actually created.
            */
            CPropSheetExt *pPropSheetExt = (CPropSheetExt*)ppsp->lParam;

            if(pPropSheetExt)
            {
                pPropSheetExt->Release();
            }
        }
        break;
    }

    return FALSE;
}

Arbeiten mit dem Benachrichtigungsobjekt

Da die Erweiterungsseiten des Eigenschaftenblatts in einem Eigenschaftenblatt angezeigt werden, das von einer der Erweiterung unbekannten Komponente erstellt wurde, muss ein "Manager" verwendet werden, um die Datenübertragung zwischen den Erweiterungsseiten und dem Eigenschaftenblatt zu verarbeiten. Dieser "Manager" wird als Benachrichtigungsobjekt bezeichnet. Das Benachrichtigungsobjekt fungiert als Moderator zwischen den einzelnen Seiten und dem Eigenschaftenblatt.

Wenn das Eigenschaftenblatterweiterungsobjekt initialisiert wird, muss die Erweiterung ein Benachrichtigungsobjekt erstellen, indem sie ADsPropCreateNotifyObj aufruft und das von IShellExtInit::Initializeabgerufene IDataObject und den Namen des Verzeichnisobjekts übergibt. Es ist nicht erforderlich, die Verweisanzahl der IDataObject-Schnittstelle zu erhöhen, da dies das von der Funktion ADsPropCreateNotifyObj erstellte Benachrichtigungsobjekt tut. Das von ADsPropCreateNotifyObj bereitgestellte Benachrichtigungsobjekthandle sollte zur späteren Verwendung gespeichert werden. ADsPropCreateNotifyObj kann entweder während IShellExtInit::Initialize oder IShellPropSheetExt::AddPages aufgerufen werden. Wenn die Eigenschaftenblatterweiterung heruntergefahren wird, muss sie eine WM_ADSPROP_NOTIFY_EXIT Nachricht an das Benachrichtigungsobjekt senden. Dadurch wird das Benachrichtigungsobjekt selbst zerstört. Dies geschieht am besten, wenn die PropSheetPageProc-Funktion die PSPCB_RELEASE Benachrichtigung empfängt.

Die Eigenschaftenblatterweiterung kann zusätzlich daten abrufen, die vom CFSTR_DSOBJECTNAMES Zwischenablageformat bereitgestellt werden, indem ADsPropGetInitInfo aufgerufen wird. Einer der Vorteile der Verwendung von ADsPropGetInitInfo besteht darin, dass sie ein IDirectoryObject-Objekt bereitstellt, das zum programmgesteuerten Arbeiten mit dem Verzeichnisobjekt verwendet wird.

Hinweis

Im Gegensatz zu den meisten COM-Methoden und -Funktionen erhöht ADsPropGetInitInfo die Verweisanzahl für das IDirectoryObject-Objekt nicht. Das IDirectoryObject darf nicht freigegeben werden, es sei denn, die Referenzanzahl wird zuerst manuell erhöht.

 

Wenn die Eigenschaftenseite zum ersten Mal erstellt wird, sollte die Erweiterung die Seite beim Benachrichtigungsobjekt registrieren, indem ADsPropSetHwnd mit dem Fensterhandle der Seite aufgerufen wird.

ADsPropCheckIfWritable ist eine Hilfsprogrammfunktion, mit der die Eigenschaftenblatterweiterung bestimmen kann, ob eine Eigenschaft geschrieben werden kann.

Verschiedenes

Das Handle der Eigenschaftenseite wird an die Prozedur des Seitendialogfelds übergeben. Das Eigenschaftenblatt ist das direkte übergeordnete Element der Eigenschaftenseite, sodass das Handle des Eigenschaftenblatts abgerufen werden kann, indem die GetParent-Funktion mit dem Eigenschaftenseitenhandle aufgerufen wird.

Wenn sich der Inhalt der Erweiterungsseite ändert, sollte die Erweiterung das makro PropSheet_Changed verwenden, um das Eigenschaftenblatt über Änderungen zu benachrichtigen. Das Eigenschaftenblatt aktiviert dann die Schaltfläche Anwenden.

Multiple-Selection Eigenschaftenblätter

Bei Windows Server 2003 und höheren Betriebssystemen unterstützen die Active Directory-Verwaltungs-MMC-Snap-Ins Eigenschaftenblatterweiterungen für mehrere Verzeichnisobjekte. Diese Eigenschaftenblätter werden angezeigt, wenn die Eigenschaften für mehrere Elemente gleichzeitig angezeigt werden. Der Hauptunterschied zwischen einer Single-Selection-Eigenschaftenblatterweiterung und einer Mehrfachauswahl-Eigenschaftenblatterweiterung besteht darin, dass die DSOBJECTNAMES-Struktur , die vom CFSTR_DSOBJECTNAMES Zwischenablageformat in IShellExtInit::Initialize bereitgestellt wird, mehr als eine DSOBJECT-Struktur enthält.

Wenn das Benachrichtigungsobjekt erstellt wird, muss eine Erweiterung für mehrere Auswahleigenschaften einen eindeutigen Namen übergeben, der vom Snap-In bereitgestellt wird, und nicht einen Namen, der von der Erweiterung erstellt wurde. Um den eindeutigen Namen zu erhalten, fordern Sie das CFSTR_DS_MULTISELECTPROPPAGE Zwischenablageformat aus dem IDataObject an, das von IShellExtInit::Initialize abgerufen wurde. Bei diesen Daten handelt es sich um eine HGLOBAL-Datei , die eine Unicode-Zeichenfolge mit Null-Endung enthält, die den eindeutigen Namen darstellt. Dieser eindeutige Name wird dann an die Funktion ADsPropCreateNotifyObj übergeben, um das Benachrichtigungsobjekt zu erstellen. Die CreateADsNotificationObject-Beispielfunktion in Beispielcode für die Implementierung des COM-Objekts des Eigenschaftenblatts veranschaulicht, wie dies ordnungsgemäß ausgeführt wird, sowie die Kompatibilität mit früheren Versionen des Snap-Ins, die keine Mehrfachauswahleigenschaftenblätter unterstützen.

Bei Eigenschaftenblättern mit mehrfacher Auswahl bindet das System nur an das erste Objekt im DSOBJECT-Array . Aus diesem Grund stellt ADsPropGetInitInfo nur die Attribute IDirectoryObject und schreibfähige Attribute für das erste Objekt im Array bereit. Die anderen Objekte im Array sind nicht an sie gebunden.

Eine Mehrfachauswahl-Eigenschaftenblatterweiterung wird unter dem attribut adminMultiselectPropertyPages registriert.

Neu mit Windows Server 2003

Die folgenden Features sind mit Windows Server 2003 neu.

Wenn auf der Eigenschaftenseite ein Fehler auftritt, kann ADsPropSendErrorMessage mit den entsprechenden Fehlerdaten aufgerufen werden. ADsPropSendErrorMessage speichert alle Fehlermeldungen in einer Warteschlange. Diese Meldungen werden beim nächsten Aufruf von ADsPropShowErrorDialog angezeigt. Wenn ADsPropShowErrorDialog zurückgibt, werden die Nachrichten in der Warteschlange gelöscht.

Windows Server 2003 führt die Funktion ADsPropSetHwndWithTitle ein . Diese Funktion ähnelt ADsPropSetHwnd, enthält aber den Seitentitel. Dadurch wird das von ADsPropShowErrorDialog angezeigte Fehlerdialogfeld aktiviert, um dem Benutzer nützlichere Daten bereitzustellen. Wenn die Eigenschaftenblatterweiterung die Funktion ADsPropShowErrorDialog verwendet, sollte die Erweiterung ADsPropSetHwndWithTitle anstelle von ADsPropSetHwnd verwenden.

Beispielcode für die Implementierung des COM-Objekts des Eigenschaftenblatts