Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Kreator strony właściwości ATL nie jest dostępny w programie Visual Studio 2019 i nowszych wersjach.
W tym przykładzie pokazano, jak utworzyć stronę właściwości wyświetlającą (i umożliwiającą zmianę) właściwości interfejsu Klasy dokumentów.
Przykład jest oparty na przykładzie ATLPages.
Aby ukończyć ten przykład, wykonasz następujące czynności:
Dodaj klasę strony właściwości ATL przy użyciu okna dialogowego Dodawanie klasy i Kreatora strony właściwości ATL.
Edytuj zasób okna dialogowego, dodając nowe kontrolki dla interesujących właściwości interfejsu
Document.Dodaj programy obsługi komunikatów w celu informowania witryny strony właściwości o zmianach wprowadzonych przez użytkownika.
Dodaj niektóre
#importinstrukcje i definicję typu w sekcji Housekeeping (Przechowywanie danych).Zastąpij element IPropertyPageImpl::SetObjects , aby zweryfikować, czy obiekty są przekazywane do strony właściwości.
Zastąpij interfejs IPropertyPageImpl::Activate , aby zainicjować interfejs strony właściwości.
Zastąpij IPropertyPageImpl::Zastosuj , aby zaktualizować obiekt przy użyciu najnowszych wartości właściwości.
Wyświetl stronę właściwości, tworząc prosty obiekt pomocnika.
Utwórz makro , które będzie testować stronę właściwości.
Dodawanie klasy strony właściwości ATL
Najpierw utwórz nowy projekt ATL dla serwera DLL o nazwie ATLPages7. Teraz użyj Kreatora strony właściwości ATL, aby wygenerować stronę właściwości. Nadaj stronie właściwości krótką nazwę dokumentu, a następnie przejdź do strony Ciągi, aby ustawić elementy specyficzne dla właściwości, jak pokazano w poniższej tabeli.
| Towar | Wartość |
|---|---|
| Tytuł | Dokument tekstowy |
| Ciąg dokumentu | Właściwości dokumentu tekstowego VCUE |
| Plik pomocy | <puste> |
Wartości ustawione na tej stronie kreatora zostaną zwrócone do kontenera strony właściwości po wywołaniu IPropertyPage::GetPageInfoelementu . Co się stanie z ciągami po tym, zależy od kontenera, ale zazwyczaj będą one używane do identyfikowania strony dla użytkownika. Tytuł będzie zwykle wyświetlany na karcie nad stroną, a ciąg dokumentu może być wyświetlany na pasku stanu lub w etykietce narzędzia (chociaż standardowa ramka właściwości w ogóle nie używa tego ciągu).
Uwaga
Ciągi ustawione w tym miejscu są przechowywane jako zasoby ciągów w projekcie przez kreatora. Możesz łatwo edytować te ciągi przy użyciu edytora zasobów, jeśli chcesz zmienić te informacje po wygenerowaniu kodu dla strony.
Kliknij przycisk OK , aby kreator wygenerował stronę właściwości.
Edytowanie zasobu okna dialogowego
Po wygenerowaniu strony właściwości należy dodać kilka kontrolek do zasobu okna dialogowego reprezentującego stronę. Dodaj pole edycji, kontrolkę tekstu statycznego oraz pole wyboru i ustaw ich identyfikatory, jak pokazano poniżej:
Te kontrolki będą używane do wyświetlania nazwy pliku dokumentu i stanu tylko do odczytu.
Uwaga
Zasób okna dialogowego nie zawiera przycisków ramek ani poleceń ani nie ma na nim karty wyglądu, którego można się spodziewać. Te funkcje są udostępniane przez ramkę strony właściwości, taką jak ta utworzona przez wywołanie elementu OleCreatePropertyFrame.
Dodawanie programów obsługi komunikatów
Za pomocą kontrolek można dodawać programy obsługi komunikatów w celu zaktualizowania stanu zanieczyszczonej strony, gdy wartość jednej z kontrolek ulegnie zmianie:
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;
}
Ten kod odpowiada na zmiany wprowadzone w kontrolce edycji lub pole wyboru, wywołując metodę IPropertyPageImpl::SetDirty, która informuje witrynę strony o zmianie. Zazwyczaj witryna strony odpowiada, włączając lub wyłączając przycisk Zastosuj na ramce strony właściwości.
Uwaga
Na własnych stronach właściwości może być konieczne śledzenie dokładnie, które właściwości zostały zmienione przez użytkownika, aby uniknąć aktualizowania właściwości, które nie zostały zmienione. Ten przykład implementuje ten kod, śledząc oryginalne wartości właściwości i porównując je z bieżącymi wartościami z interfejsu użytkownika, gdy nadszedł czas na zastosowanie zmian.
Konserwacja
Teraz dodaj kilka instrukcji #import do pliku DocProperties.h, aby kompilator wiedział o interfejsie Document :
// 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
Należy również odwołać się do klasy bazowej IPropertyPageImpltypedef. Dodaj następujące CDocProperties elementy do klasy:
typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;
Zastępowanie obiektu IPropertyPageImpl::SetObjects
Pierwszą IPropertyPageImpl metodą, którą należy zastąpić, jest SetObjects. W tym miejscu dodasz kod, aby sprawdzić, czy przekazano tylko jeden obiekt i czy obsługuje Document oczekiwany interfejs:
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;
}
Uwaga
Warto obsługiwać tylko jeden obiekt dla tej strony, ponieważ pozwolisz użytkownikowi ustawić nazwę pliku obiektu — tylko jeden plik może istnieć w dowolnej lokalizacji.
Zastępowanie elementu IPropertyPageImpl::Activate
Następnym krokiem jest zainicjowanie strony właściwości przy użyciu wartości właściwości obiektu bazowego po pierwszym utworzeniu strony.
W takim przypadku należy dodać następujące elementy członkowskie do klasy, ponieważ użyjesz również początkowych wartości właściwości do porównania, gdy użytkownicy strony zastosują swoje zmiany:
CComBSTR m_bstrFullName; // The original name
VARIANT_BOOL m_bReadOnly; // The original read-only state
Implementacja klasy bazowej metody Activate jest odpowiedzialna za utworzenie okna dialogowego i jego kontrolek, dzięki czemu można zastąpić tę metodę i dodać własną inicjację po wywołaniu klasy bazowej:
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;
}
Ten kod używa metod COM interfejsu Document , aby uzyskać interesujące Cię właściwości. Następnie używa otoek interfejsu API Win32 dostarczonego przez aplikację CDialogImpl i jej klas bazowych, aby wyświetlić wartości właściwości użytkownikowi.
Zastępowanie elementu IPropertyPageImpl::Apply
Gdy użytkownicy chcą zastosować zmiany do obiektów, witryna strony właściwości wywoła metodę Apply . Jest to miejsce, w których należy wykonać odwrotność kodu Activate — podczas gdy Activate pobierało wartości z obiektu i wypychało je do kontrolek na stronie właściwości, Apply pobiera wartości z kontrolek na stronie właściwości i wypycha je do obiektu.
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;
}
Uwaga
Sprawdzanie względem m_bDirty na początku tej implementacji jest początkowym sprawdzaniem, aby uniknąć niepotrzebnych aktualizacji obiektów, jeśli Apply jest wywoływany więcej niż raz. Istnieją również kontrole względem każdej wartości właściwości, aby upewnić się, że tylko zmiany powodują wywołanie metody do Documentklasy .
Uwaga
Document uwidacznia FullName jako właściwość tylko do odczytu. Aby zaktualizować nazwę pliku dokumentu na podstawie zmian wprowadzonych na stronie właściwości, należy użyć Save metody w celu zapisania pliku pod inną nazwą. W związku z tym kod na stronie właściwości nie musi ograniczać się do pobierania lub ustawiania właściwości.
Wyświetlanie strony właściwości
Aby wyświetlić tę stronę, należy utworzyć prosty obiekt pomocnika. Obiekt pomocnika udostępnia metodę, która upraszcza OleCreatePropertyFrame interfejs API do wyświetlania pojedynczej strony połączonej z pojedynczym obiektem. Ten pomocnik zostanie zaprojektowany tak, aby mógł być używany z poziomu języka Visual Basic.
Użyj okna dialogowego Dodawanie klasy i Kreatora prostego obiektu ATL, aby wygenerować nową klasę i użyć Helper jej jako krótkiej nazwy. Po utworzeniu dodaj metodę, jak pokazano w poniższej tabeli.
| Towar | Wartość |
|---|---|
| Nazwa metody | ShowPage |
| Parametry | [in] BSTR bstrCaption, [in] BSTR bstrID, [in] IUnknown* pUnk |
Parametr bstrCaption to podpis, który ma być wyświetlany jako tytuł okna dialogowego. Parametr bstrID to ciąg reprezentujący identyfikator CLSID lub identyfikator ProgID strony właściwości do wyświetlenia.
Parametr pUnk będzie wskaźnikiem IUnknown obiektu, którego właściwości zostaną skonfigurowane przez stronę właściwości.
Zaimplementuj metodę, jak pokazano poniżej:
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
);
}
Tworzenie makra
Po skompilowania projektu możesz przetestować stronę właściwości i obiekt pomocnika przy użyciu prostego makra, które można utworzyć i uruchomić w środowisku projektowym programu Visual Studio. To makro utworzy obiekt pomocnika, a następnie wywoła metodę ShowPage przy użyciu identyfikatora ProgID strony właściwości DocProperties i IUnknown wskaźnika dokumentu aktualnie aktywnego w edytorze programu Visual Studio. Poniższy kod potrzebny do tego makra:
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
Po uruchomieniu tego makra zostanie wyświetlona strona właściwości przedstawiająca nazwę pliku i stan tylko do odczytu aktualnie aktywnego dokumentu tekstowego. Stan tylko do odczytu dokumentu odzwierciedla możliwość zapisu w dokumencie w środowisku projektowym; nie ma wpływu na atrybut tylko do odczytu pliku na dysku.