Freigeben über


Example: Implementing a Property Page

Dieses Beispiel zeigt, wie eine Eigenschaftenseite erstellt, die (ermöglicht die Änderung) Eigenschaften der Dokumentklassen-Schnittstelle anzeigt. Diese Schnittstelle wird von Dokumente in Beispiele für das Objektmodell der allgemeinen Umgebung von Visual Studio verfügbar gemacht (obwohl die Eigenschaftenseite, die Sie erstellen, nicht wissen, wo die Objekte es stammen von bearbeitet, solange sie die richtige Schnittstelle unterstützen).

Das Beispiel basiert auf ATLPages-Beispiel.

Um dieses Beispiel zu vervollständigen, werden Sie:

  • Fügen Sie die ATL-Eigenschaftenseitenklasse hinzu mithilfe des Hinzufügens-Klassendialogfelds und des ATL-Eigenschaftenseiten-Assistenten.

  • Bearbeiten Sie die Dialogfeldressource durch Hinzufügen von neuen Steuerelementen für die interessanten Eigenschaften der Document-Schnittstelle.

  • Fügen Sie Meldungshandler hinzu, um die Eigenschaftenseitensite laufend über die vorgenommenen Änderungen vom Benutzer.

  • Fügen Sie mehrere #import-Anweisungen und Typedef im Haushaltung-Abschnitt hinzu.

  • Überschreiben Sie IPropertyPageImpl::SetObjects, um die Objekte, die für die Eigenschaftenseite sicherzustellen übergeben werden.

  • Überschreiben IPropertyPageImpl::Activate, um die Schnittstelle der Eigenschaftenseite zu initialisieren.

  • Überschreiben IPropertyPageImpl::Apply, um des Objekts mit den neuesten Eigenschaftswerten zu aktualisieren.

  • Zeigen Sie die Eigenschaftenseite an durch das Erstellen eines einfachen Hilfeobjekts.

  • Erstellen Sie ein Makro, das die Eigenschaftenseite testet.

Hinzufügen der ATL-Eigenschaftenseiten-Klasse

Zunächst erstellen Sie ein neues ATL-Projekt für einen DLL-Server, der ATLPages7 aufgerufen wird. Verwenden Sie jetzt ATL-Eigenschaftenseiten-Assistent, um eine Eigenschaftenseite zu generieren. Geben Sie, der Eigenschaftenseite Kurzname von DocProperties fahren Sie zu Zeichenfolgen die Seite, um Eigenschaft-Seitebesondere Elemente wie in der Tabelle unten dargestellt festzulegen.

Element

Wert

Titel

TextDocument

Doc Zeichenfolgen-.

Eigenschaften VCUE TextDocument

werden

<blank>

Die Werte, die Sie festgelegt auf dieser Seite des Assistenten zum Eigenschaftenseitencontainer zurückgegeben werden, wenn sie IPropertyPage::GetPageInfo aufruft. Was in Zeichenfolgen nach geschieht, das vom Container, aber abhängig ist, in der Regel werden sie verwendet, um die Seite an den Benutzer zu identifizieren. Der Name wird normalerweise in einer Registerkarte zu der Seite und die Doc. Zeichenfolgen- wird in einer Statusleiste oder in einer QuickInfo angezeigt werden (wenn auch der Standardeigenschaftenrahmen nicht diese Zeichenfolge vorhanden verwendet).

Hinweis

Die Zeichenfolgen, dass Sie hier festgelegt wie Zeichenfolgenressourcen im Projekt vom Assistenten gespeichert werden.Sie können diese Zeichenfolgen mithilfe des Ressourcen-Editor bequem bearbeiten, wenn Sie diese Informationen ändern, nachdem der Code für die Seite generiert wurde.

OK auf das Erstellen des Assistenten die Eigenschaftenseite generieren.

Bearbeiten der Dialogfeldressource

Nachdem die Eigenschaftenseite generiert wurde, müssen Sie mehrere Steuerelemente der Dialogfeldressource hinzufügen, die die Seite darstellt. Fügen Sie ein Eingabefeld, ein Steuerelement Statischer Text und ein Kontrollkästchen hinzu und legen Sie deren IDs wie unten dargestellt fest:

Dialogfeldressource bearbeiten

Diese Steuerelemente werden verwendet, um den Dateinamen des Dokuments und des schreibgeschützten Status anzuzeigen.

Hinweis

Die Dialogressource enthält nicht Rahmens oder Befehlsschaltflächen, noch verfügt sie die Darstellung im Registerkartenformat, den Sie möglicherweise erwartet.Diese Funktionen werden von Eigenschaftenseitenframen wie dem bereitgestellt, das mit OleCreatePropertyFrame erstellt wird, aufgerufen.

Hinzufügen von Meldungshandlern

Mit den Steuerelemente erstellt haben, können Sie Meldungshandler hinzufügen, um den geänderten Status der Seite zu aktualisieren, wenn der Wert aus einer der Kontrollenänderungen:

BEGIN_MSG_MAP(CDocProperties)
   COMMAND_HANDLER(IDC_NAME, EN_CHANGE, OnUIChange)
   COMMAND_HANDLER(IDC_READONLY, BN_CLICKED, OnUIChange)
   CHAIN_MSG_MAP(IPropertyPageImpl<CDocProperties>)
END_MSG_MAP()

   // Respond to changes in the UI to update the dirty status of the page
   LRESULT OnUIChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
   {
      wNotifyCode; wID; hWndCtl; bHandled;
      SetDirty(true);
      return 0;
   }

Dieser Code reagiert auf die Änderungen, die am Bearbeitungssteuerelement oder am Kontrollkästchen, indem er IPropertyPageImpl::SetDirty vorgenommen werden aufruft, der die Seitensite informiert, dass die Seite geändert hat. In der Regel reagiert die Seitensite, indem eine Übernehmen Schaltfläche auf den Eigenschaftenseitenframen aktiviert oder deaktiviert.

Hinweis

In Ihren eigenen Eigenschaftenseiten müssen Sie möglicherweise genau verfolgen, das Eigenschaften vom Benutzer geändert wurden, sodass Sie Eigenschaften zu aktualisieren, vermeiden können, die nicht geändert wurden.implementiert dieses Beispiels, die Code, indem die ursprünglichen Eigenschaftswerte verfolgen und mit den aktuellen Werten des Benutzeroberfläche vergleichen, wenn es Zeit ist, die Änderungen zu übernehmen.

Haushaltung

Fügen Sie nun ein paar #import-Anweisungen DocProperties.h hinzu, damit der Compiler in der Document-Schnittstelle bemerkt:

// MSO.dll
#import <libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52> version("2.2") \
   rename("RGB", "Rgb")   \
   rename("DocumentProperties", "documentproperties")   \
   rename("ReplaceText", "replaceText")   \
   rename("FindText", "findText")   \
   rename("GetObject", "getObject")   \
   raw_interfaces_only

// dte.olb
#import <libid:80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2> \
   inject_statement("using namespace Office;")   \
   rename("ReplaceText", "replaceText")   \
   rename("FindText", "findText")   \
   rename("GetObject", "getObject")   \
   rename("SearchPath", "searchPath")   \
   raw_interfaces_only

Sie müssen auch die IPropertyPageImpl Basisklasse verweisen; Fügen Sie folgenden typedef der CDocProperties-Klasse hinzu:

typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;

Überschreiben von IPropertyPageImpl::SetObjects

Die erste IPropertyPageImpl-Methode, die Sie überschreiben müssen, ist SetObjects. Hier fügen Sie Code hinzu, um zu überprüfen, dass nur ein einzelnes Objekt übergeben wurde und dass die Document-Schnittstelle unterstützt, die Sie erwarten:

STDMETHOD(SetObjects)(ULONG nObjects, IUnknown** ppUnk)
{
   HRESULT hr = E_INVALIDARG;
   if (nObjects == 1)
   {
      CComQIPtr<EnvDTE::Document> pDoc(ppUnk[0]);
      if (pDoc)
         hr = PPGBaseClass::SetObjects(nObjects, ppUnk);
   }
   return hr;
}

Hinweis

Sie ist sinnvoll, nur ein einzelnes Objekt für diese Seite zu unterstützen, da Sie dem Benutzer ermöglichen, den Dateinamen des Objekts festzulegen - nur eine Datei kann an jedem an einem Speicherort vorhanden sein.

Überschreiben von IPropertyPageImpl::Activate

Der nächste Schritt besteht darin, die Eigenschaftenseite mit den Eigenschaftswerten des zugrunde liegenden Objekts zu initialisieren, wenn die Seite zum ersten Mal erstellt wird.

In diesem Fall sollten Sie die folgenden Member der Klasse hinzufügen, während Sie auch die Anfangswerte der Eigenschaft für den Vergleich verwenden, wenn Benutzer der Seite ihre Änderungen anwenden:

CComBSTR m_bstrFullName;  // The original name
VARIANT_BOOL m_bReadOnly; // The original read-only state

Die Basisklassenimplementierung der Methode Aktivieren Sie ist für das Erstellen des Dialogfelds und ihrer Steuerelemente verantwortlich, sodass Sie diese Methode überschreiben und eine eigene Initialisierung hinzufügen, nachdem Sie die Basisklasse aufgerufen haben:

STDMETHOD(Activate)(HWND hWndParent, LPCRECT prc, BOOL bModal)
{
   // If we don't have any objects, this method should not be called
   // Note that OleCreatePropertyFrame will call Activate even if
   // a call to SetObjects fails, so this check is required
   if (!m_ppUnk)
      return E_UNEXPECTED;

   // Use Activate to update the property page's UI with information
   // obtained from the objects in the m_ppUnk array

   // We update the page to display the Name and ReadOnly properties
   // of the document

   // Call the base class
   HRESULT hr = PPGBaseClass::Activate(hWndParent, prc, bModal);
   if (FAILED(hr))
      return hr;

   // Get the EnvDTE::Document pointer
   CComQIPtr<EnvDTE::Document> pDoc(m_ppUnk[0]);
   if (!pDoc)
      return E_UNEXPECTED;

   // Get the FullName property
   hr = pDoc->get_FullName(&m_bstrFullName);
   if (FAILED(hr))
      return hr;

   // Set the text box so that the user can see the document name
   USES_CONVERSION;
   SetDlgItemText(IDC_NAME, CW2CT(m_bstrFullName));

   // Get the ReadOnly property
   m_bReadOnly = VARIANT_FALSE;
   hr = pDoc->get_ReadOnly(&m_bReadOnly);
   if (FAILED(hr))
      return hr;

   // Set the check box so that the user can see the document's read-only status
   CheckDlgButton(IDC_READONLY, m_bReadOnly ? BST_CHECKED : BST_UNCHECKED);

   return hr;
}

Dieser Code verwendet die COM-Methoden der Document-Schnittstelle, um die Eigenschaften zu erhalten, die Sie sich interessieren. Er verwendet dann die Win32 API-Wrapper, die von CDialogImpl und von den Basisklassen bereitgestellt werden, damit die Eigenschaftswerte für den Benutzer anzuzeigen.

Überschreiben von IPropertyPageImpl::Apply

Wenn Benutzer ihre Änderungen an Objekten anwenden möchten, ruft die Eigenschaftenseitensite die Wenden Sie an-Methode auf. Dies ist der Platz, um die Rückseite des Codes in Activate auszuführen - während Activate-Werte aus dem Objekt dauerte und in die Steuerelemente auf der Eigenschaftenseite hat, nimmt Übernehmen-Werte von Steuerelementen auf der Eigenschaftenseite und legt sie in das Objekt.

STDMETHOD(Apply)(void)
{
   // If we don't have any objects, this method should not be called
   if (!m_ppUnk)
      return E_UNEXPECTED;

   // Use Apply to validate the user's settings and update the objects'
   // properties

   // Check whether we need to update the object
   // Quite important since standard property frame calls Apply
   // when it doesn't need to
   if (!m_bDirty)
      return S_OK;

   HRESULT hr = E_UNEXPECTED;

   // Get a pointer to the document
   CComQIPtr<EnvDTE::Document> pDoc(m_ppUnk[0]);
   if (!pDoc)
      return hr;

   // Get the read-only setting
   VARIANT_BOOL bReadOnly = IsDlgButtonChecked(IDC_READONLY) ? VARIANT_TRUE : VARIANT_FALSE;

   // Get the file name
   CComBSTR bstrName;
   if (!GetDlgItemText(IDC_NAME, bstrName.m_str))
      return E_FAIL;

   // Set the read-only property
   if (bReadOnly != m_bReadOnly)
   {
      hr = pDoc->put_ReadOnly(bReadOnly);
      if (FAILED(hr))
         return hr;
   }

   // Save the document
   if (bstrName != m_bstrFullName)
   {
      EnvDTE::vsSaveStatus status;
      hr = pDoc->Save(bstrName, &status);
      if (FAILED(hr))
         return hr;
   }

   // Clear the dirty status of the property page
   SetDirty(false);

   return S_OK;
}

Hinweis

Die Überprüfung anhand m_bDirty am Anfang dieser Implementierung ist eine ursprüngliche Überprüfung, um für unnötige Aktualisierungen der Objekte zu vermeiden, wenn Übernehmen mehrmals aufgerufen wird.Es gibt auch Überprüfungen für jeden der Eigenschaftswerte, sicherzustellen, dass nur Änderungen Methodenaufruf zu Document führen.

Hinweis

Document macht FullName als schreibgeschützte Eigenschaft.Um den Dateinamen des Dokuments auf Grundlage der Änderungen, die an der Eigenschaftenseite zu aktualisieren vorgenommen werden, müssen Sie die Methode verwenden Speichern um die Datei mit einem anderen Namen zu speichern.Daher muss der Code in einer Eigenschaftenseite nicht zum Abrufen oder zum Festlegen von Eigenschaften beschränken.

Anzeigen der Eigenschaftenseite

Um diese Seite anzuzeigen, müssen Sie ein einfaches Hilfsobjekt erstellen. Das Hilfsobjekt bietet eine Möglichkeit, die das OleCreatePropertyFrame API zum Anzeigen einer einzelnen Seite vereinfacht, die an ein einzelnes Objekt verbunden ist. Diese Hilfe ist so konzipiert, dass sie aus Visual Basic verwendet werden kann.

Verwenden Sie Fügen Sie Klassendialogfeld hinzu und ATL-Assistent für einfache Objekte, um eine neue Klasse zu generieren und Helper als Kurzname zu verwenden. Einmal erstellt, fügen Sie eine Methode wie in der Tabelle unten dargestellt hinzu.

Element

Wert

Methodenname

ShowPage

Parameter

[in] BSTR bstrCaption, [in] BSTR bstrID, [in] IUnknown* pUnk

Der bstrCaption-Parameter ist die als Titel des Dialogfelds angezeigt werden Beschriftung. Der bstrID-Parameter ist eine Zeichenfolge, die entweder eine CLSID oder eine ProgID der Eigenschaftenseite darstellt, um anzuzeigen. Der pUnk-Parameter ist der IUnknown Zeiger des Objekts, dessen Eigenschaften über die Eigenschaftenseite konfiguriert werden.

Implementieren Sie die Methode wie unten dargestellt:

STDMETHODIMP CHelper::ShowPage(BSTR bstrCaption, BSTR bstrID, IUnknown* pUnk)
{
   if (!pUnk)
      return E_INVALIDARG;

   // First, assume bstrID is a string representing the CLSID 
   CLSID theCLSID = {0};
   HRESULT hr = CLSIDFromString(bstrID, &theCLSID);
   if (FAILED(hr))
   {
      // Now assume bstrID is a ProgID
      hr = CLSIDFromProgID(bstrID, &theCLSID);
      if (FAILED(hr))
         return hr;
   }

   // Use the system-supplied property frame 
   return OleCreatePropertyFrame(
      GetActiveWindow(),   // Parent window of the property frame
      0,           // Horizontal position of the property frame
      0,           // Vertical position of the property frame
      bstrCaption, // Property frame caption
      1,           // Number of objects
      &pUnk,       // Array of IUnknown pointers for objects
      1,           // Number of property pages
      &theCLSID,   // Array of CLSIDs for property pages
      NULL,        // Locale identifier
      0,           // Reserved - 0
      NULL         // Reserved - 0
      );
}

Erstellen eines Makros

Nachdem Sie das Projekt erstellt haben, können Sie die Eigenschaftenseite und das Hilfsobjekt mithilfe eines einfachen Makros testen, dass Sie in der Visual Studio-Entwicklungsumgebung erstellen und ausführen können. Dieses Makro erstellt ein Hilfsobjekt, ruft die ShowPage-Methode mit dem ProgID der DocProperties-Eigenschaftenseite und des IUnknown Zeigers des Dokuments derzeit aktiv im Visual Studio-Editor auf. Der Code, den Sie für dieses Makro erfordern, wird unten dargestellt:

Imports EnvDTE
Imports System.Diagnostics

Public Module AtlPages

    Public Sub Test()
        Dim Helper
        Helper = CreateObject("ATLPages7.Helper.1")

        On Error Resume Next
        Helper.ShowPage( _
            ActiveDocument.Name, _
            "ATLPages7Lib.DocumentProperties.1", _
            DTE.ActiveDocument _
            )
    End Sub

End Module

Wenn Sie dieses Makro ausführen, wird die Eigenschaftenseite den Dateinamen und den schreibgeschützten Status des aktiven Textdokuments nur für angezeigt. Der schreibgeschützte Zustand des Dokuments gibt nur die Möglichkeit, dem Dokument in der Entwicklungsumgebung zu schreiben; sie wirkt sich nicht auf das Schreibschutzattribut der Datei auf dem Datenträger.

Siehe auch

Konzepte

ATL COM-Eigenschaftenseiten

ATLPages-Beispiel