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řidejte třídu stránky vlastností ATL pomocí dialogového okna Přidat třídu a Průvodce stránkou vlastností ATL.
Upravte prostředek dialogového okna přidáním nových ovládacích prvků pro zajímavé vlastnosti
Document
rozhraní.Přidejte obslužné rutiny zpráv, aby byl web stránky vlastností informován o změnách provedených uživatelem.
Do oddílu Housekeeping přidejte některé
#import
příkazy a typedef.Přepsat IPropertyPageImpl::SetObjects ověřit objekty předávané na stránku vlastnosti.
Přepsat IPropertyPageImpl::Activate inicializovat rozhraní stránky vlastností.
Override IPropertyPageImpl::Apply to update the object with the latest property values.
Umožňuje zobrazit stránku vlastností vytvořením jednoduchého pomocného objektu.
Vytvořte makro , které otestuje stránku vlastností.
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ázev DocProperties 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 |
---|---|
Nadpis | Textový dokument |
Řetězec dokumentu | Vlastnosti textového dokumentu VCUE |
Soubor nápovědy | <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:
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í Document
metody .
Poznámka:
Document
FullName
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 titulek, 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.