Sdílet prostřednictvím


Příklad: Implementace stránky vlastností

Průvodce stránkou vlastností ATL není v sadě Visual Studio 2019 a novější k dispozici.

Tento příklad ukazuje, jak vytvořit stránku vlastností, která zobrazuje (a umožňuje změnit) vlastnosti rozhraní Třídy dokumentů.

Příklad je založený na ukázce ATLPages.

K dokončení tohoto příkladu budete:

Přidání třídy stránky vlastností ATL

Nejprve vytvořte nový projekt ATL pro server knihovny DLL s názvem ATLPages7. Teď pomocí Průvodce stránkou vlastností ATL vygenerujte stránku vlastností. Na stránce vlastností zadejte krátký názevDocProperties a pak přepněte na stránku Řetězce a nastavte položky specifické pro vlastnosti, jak je znázorněno v následující tabulce.

Zboží Hodnota
Titulek Textový dokument
Řetězec dokumentu Vlastnosti textového dokumentu VCUE
Helpfile <prázdný>

Hodnoty, které jste nastavili na této stránce průvodce, budou vráceny do kontejneru stránky vlastností při volání IPropertyPage::GetPageInfo. Co se stane s řetězci po tom, co je závislé na kontejneru, ale obvykle se použijí k identifikaci vaší stránky pro uživatele. Název se obvykle zobrazí na kartě nad vaší stránkou a řetězec dokumentu se může zobrazit na stavovém řádku nebo popisku (i když standardní rámec vlastností tento řetězec vůbec nepoužívá).

Poznámka

Řetězce, které tady nastavíte, se uloží jako řetězcové prostředky v projektu průvodcem. Tyto řetězce můžete snadno upravit pomocí editoru prostředků, pokud po vygenerování kódu stránky potřebujete tyto informace změnit.

Chcete-li, aby průvodce vygeneroval stránku vlastností, klikněte na tlačítko OK .

Úprava prostředku dialogového okna

Po vygenerování stránky vlastností budete muset do prostředku dialogového okna představujícího vaši stránku přidat několik ovládacích prvků. Přidejte textové pole, statický textový ovládací prvek a zaškrtávací políčko a nastavte jejich ID, jak je znázorněno níže:

Screenshot of a dialog resource in the visual editor.

Tyto ovládací prvky se použijí k zobrazení názvu souboru dokumentu a jeho stavu jen pro čtení.

Poznámka

Prostředek dialogového okna neobsahuje rámeček ani příkazová tlačítka ani neobsahuje vzhled karet, který jste očekávali. Tyto funkce jsou poskytovány rámečkem stránky vlastností, jako je například objekt vytvořený voláním OleCreatePropertyFrame.

Přidání obslužných rutin zpráv

Když se změní hodnota některého z ovládacích prvků, můžete přidat obslužné rutiny zpráv, které aktualizují stav stránky, když se změní hodnota některého z ovládacích prvků:

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;
   }

Tento kód reaguje na změny provedené v ovládacím prvku pro úpravy nebo zaškrtávací políčko zavoláním IPropertyPageImpl::SetDirty, který informuje web stránky, že se stránka změnila. Web stránky obvykle reaguje povolením nebo zakázáním tlačítka Použít v rámci stránky vlastností.

Poznámka

Na vlastních stránkách vlastností možná budete muset sledovat přesně to, které vlastnosti uživatel změnil, abyste se vyhnuli aktualizaci vlastností, které nebyly změněny. Tento příklad implementuje tento kód tak, že udržuje přehled o původních hodnotách vlastností a porovnává je s aktuálními hodnotami z uživatelského rozhraní, když je čas použít změny.

Údržba

Teď přidejte do DocProperties.h několik #import příkazů, aby kompilátor věděl o Document rozhraní:

// 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

Budete také muset odkazovat na IPropertyPageImpl základní třídu. Přidejte do CDocProperties třídy následujícítypedef:

typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;

Přepsání IPropertyPageImpl::SetObjects

První IPropertyPageImpl metoda, kterou potřebujete přepsat, je SetObjects. Tady přidáte kód, který zkontroluje, že byl předán pouze jeden objekt a že podporuje Document rozhraní, které očekáváte:

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;
}

Poznámka

Dává smysl podporovat pouze jeden objekt pro tuto stránku, protože umožníte uživateli nastavit název souboru objektu – na jednom místě může existovat pouze jeden soubor.

Přepsání IPropertyPageImpl::Activate

Dalším krokem je inicializace stránky vlastností s hodnotami vlastností podkladového objektu při prvním vytvoření stránky.

V tomto případě byste měli do třídy přidat následující členy, protože použijete také počáteční hodnoty vlastností pro porovnání, když uživatelé stránky použijí změny:

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

Implementace základní třídy metody Activate je zodpovědná za vytvoření dialogového okna a jeho ovládacích prvků, takže můžete tuto metodu přepsat a přidat vlastní inicializaci po volání základní třídy:

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;
}

Tento kód používá metody Document MODELU COM rozhraní k získání vlastností, které vás zajímají. Pak používá obálky rozhraní API Win32 poskytované CDialogImpl a jeho základní třídy k zobrazení hodnot vlastností pro uživatele.

Přepsání IPropertyPageImpl::Apply

Když uživatelé chtějí použít změny na objekty, web stránky vlastností bude volat Metodu Apply . Jedná se o místo, kde lze provést obrácený kód Activate – zatímco Activate vzal hodnoty z objektu a vložil je do ovládacích prvků na stránce vlastností, Apply přebírá hodnoty z ovládacích prvků na stránce vlastnosti a nasdílí je do objektu.

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;
}

Poznámka

Kontrola m_bDirty na začátku této implementace je počáteční kontrola, která zabraňuje zbytečným aktualizacím objektů, pokud Apply se volá více než jednou. Existují také kontroly proti každé z hodnot vlastností, aby se zajistilo, že pouze změny způsobí volání Documentmetody .

Poznámka

DocumentFullName zveřejňuje jako vlastnost jen pro čtení. Chcete-li aktualizovat název souboru dokumentu na základě změn provedených na stránce vlastností, musíte použít Save metodu k uložení souboru s jiným názvem. Kód na stránce vlastností se tedy nemusí omezovat na získání nebo nastavení vlastností.

Zobrazení stránky vlastností

Chcete-li zobrazit tuto stránku, musíte vytvořit jednoduchý pomocný objekt. Pomocný objekt poskytne metodu, která zjednodušuje OleCreatePropertyFrame rozhraní API pro zobrazení jedné stránky připojené k jednomu objektu. Tato pomocná rutina bude navržena tak, aby ji bylo možné použít z jazyka Visual Basic.

Pomocí dialogového okna Přidat třídu a Průvodce jednoduchým objektem ATL vygenerujte novou třídu a použijte Helper ji jako její krátký název. Po vytvoření přidejte metodu, jak je znázorněno v následující tabulce.

Zboží Hodnota
Název metody ShowPage
Parametry [in] BSTR bstrCaption, [in] BSTR bstrID, [in] IUnknown* pUnk

Parametr bstrCaption je popis, který se má zobrazit jako název dialogového okna. Parametr bstrID je řetězec představující buď CLSID , nebo ProgID stránky vlastností, která se má zobrazit. Parametr pUnk bude ukazatelem IUnknown objektu, jehož vlastnosti budou nakonfigurovány stránkou vlastností.

Implementujte metodu, jak je znázorněno níže:

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
      );
}

Vytvoření makra

Po sestavení projektu můžete stránku vlastností a pomocný objekt otestovat pomocí jednoduchého makra, které můžete vytvořit a spustit ve vývojovém prostředí sady Visual Studio. Toto makro vytvoří pomocný objekt a potom zavolá jeho ShowPage metodu pomocí ProgID stránky vlastností DocProperties a IUnknown ukazatele dokumentu, který je aktuálně aktivní v editoru sady Visual Studio. Níže je uvedený kód, který potřebujete pro toto makro:

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

Při spuštění tohoto makra se zobrazí stránka vlastností se stavem názvu souboru a stavu jen pro čtení aktuálně aktivního textového dokumentu. Stav dokumentu jen pro čtení odráží schopnost zapisovat do dokumentu ve vývojovém prostředí; nemá vliv na atribut souboru jen pro čtení na disku.

Viz také

Stránky vlastností
Ukázka ATLPages