Esempio: Implementare una pagina delle proprietà
In questo esempio viene illustrato come compilare una pagina delle proprietà visualizzate (consente di modificare) le proprietà dell'interfaccia Classi di documento.Questa interfaccia è esposta da documenti in Esempi del modello a oggetti dell'ambiente comune di Visual Studio (sebbene la pagina delle proprietà che non si creerà preoccupi da cui gli oggetti modifica e che supportano l'interfaccia corretta).
l'esempio è basato su Esempio ATLPages.
Per completare questo esempio, sarà:
Aggiungere la classe della pagina delle proprietà ATL utilizzando la finestra di dialogo della classe aggiunta e della pagina delle proprietà ATL.
Modificare la finestra di dialogo aggiungendo nuovi controlli per le proprietà interessanti dell'interfaccia Documento.
Aggiungere gestori di messaggi al sito della pagina delle proprietà presenti le modifiche apportate dall'utente.
Aggiungere alcune istruzioni #import e un typedef nella sezione Governo di cane.
Eseguire l'override di IPropertyPageImpl::SetObjects per convalidare gli oggetti passati alla pagina delle proprietà.
override IPropertyPageImpl::Activate per inizializzare l'interfaccia della pagina delle proprietà.
override IPropertyPageImpl::Apply per aggiornare l'oggetto con gli ultimi valori della proprietà.
Visualizzare la pagina delle proprietà creando un oggetto di supporto semplice.
Creare una macro che collauderà la pagina delle proprietà.
Aggiunta della classe della pagina delle proprietà ATL
Innanzitutto, creare un nuovo progetto ATL per un server di DLL denominato ATLPages7.Ora Procedura guidata della pagina delle proprietà ATL utilizzare per generare una pagina delle proprietà.Assegnare alla pagina delle proprietà nome breveDocProperties quindi l'opzione nella pagina Strings agli elementi proprietà-pagina- specifici definiti come illustrato nella tabella riportata di seguito.
Elemento |
Valore |
---|---|
Titolo |
TextDocument |
Stringa del documento |
Proprietà di VCUE TextDocument |
File |
<blank> |
I valori impostate in questa pagina della procedura guidata verrà restituito al contenitore della pagina delle proprietà quando chiama IPropertyPage::GetPageInfo.Ciò che si verifica dopo le stringhe che dipende dal contenitore, ma in genere verranno utilizzati per identificare la pagina all'utente.Il titolo in genere visualizzato in una scheda sulla pagina e la stringa di documenti possono essere visualizzati in una barra di stato o in una descrizione comando (sebbene la finestra delle proprietà standard non utilizzare questa stringa alcuno).
[!NOTA]
Le stringhe impostato qui è archiviato come risorsa di tipo stringa nel progetto tramite la procedura guidata.È possibile modificare queste stringhe utilizzando l'editor di risorse se è necessario modificare queste informazioni dopo il codice della pagina è stato generato.
Scegliere OK per la procedura guidata deve generare la pagina delle proprietà.
Modificare la risorsa finestra di dialogo
Ora che la pagina delle proprietà è stata generata un'eccezione, è necessario aggiungere alcuni controlli alla risorsa finestra di dialogo che rappresenta la pagina.Aggiungere una casella di modifica, un controllo di testo statico e una casella di controllo e impostare i relativi ID come illustrato di seguito:
Questi controlli saranno utilizzati per visualizzare il nome file del documento e il relativo stato in sola lettura.
[!NOTA]
La finestra di dialogo non include un frame o i pulsanti di comando, né ha l'aspetto a schede che previsto.Queste funzionalità fornite da un frame di pagina delle proprietà come quello creato chiamando OleCreatePropertyFrame.
Gestori di messaggi di aggiunta
Con i controlli sul posto, è possibile aggiungere gestori di messaggi per aggiornare lo stato modificato della pagina quando il valore di uno delle modifiche dei comandi:
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;
}
Questo codice risposta alle modifiche apportate al controllo di modifica o la casella di controllo chiamando IPropertyPageImpl::SetDirty, che informa il sito della pagina che la pagina è stata modificata.In genere il sito della pagina risponda abilitazione o disabilitazione di un pulsante Apply sul frame di pagina delle proprietà.
[!NOTA]
Nelle rispettive pagine delle proprietà, potrebbe essere necessario tenere traccia con precisione che le proprietà sono state alterate dall'utente in modo da evitare possibile aggiornare le proprietà che non sono state modificate.Implementazione di questo esempio di codice tenendo traccia dei valori di proprietà originali e confrontandoli con i valori correnti dell'interfaccia utente al momento di applicare le modifiche.
Governo di cane
Aggiungere una coppia di istruzioni #import a DocProperties.h in modo che il compilatore sia sull'interfaccia Documento :
// 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
Sarà inoltre necessario fare riferimento alla classe base IPropertyPageImpl ; aggiungere typedef seguente alla classe CDocProperties :
typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;
Eseguire l'override di IPropertyPageImpl::SetObjects
Il primo metodo IPropertyPageImpl che è necessario eseguire l'override è SetObjects.Di seguito verrà aggiunto il codice per verificare che un solo oggetto venga passato e supporta l'interfaccia Documento che si prevede:
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;
}
[!NOTA]
È opportuno supportare un solo oggetto per questa pagina poiché si consentirà all'utente di impostare il nome file dell'oggetto da un solo file esista in una posizione.
Eseguire l'override di IPropertyPageImpl::Activate
È necessario inizializzare la pagina delle proprietà con i valori della proprietà dell'oggetto sottostante durante la prima pagina della creazione.
In questo caso è necessario aggiungere i membri seguenti alla classe poiché si utilizzerà inoltre i valori di proprietà iniziali per il confronto quando gli utenti della pagina applicate le modifiche:
CComBSTR m_bstrFullName; // The original name
VARIANT_BOOL m_bReadOnly; // The original read-only state
L'implementazione della classe base del metodo Attiva è necessario creare la finestra di dialogo e i comandi, pertanto è possibile eseguire l'override di questo metodo e aggiungere la propria inizializzazione dopo avere definito la classe base:
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;
}
Questo codice utilizza i metodi COM l'interfaccia Documento per ottenere le proprietà desiderate.Quindi utilizza i wrapper di API Win32 forniti da CDialogImpl e le relative classi base per visualizzare i valori della proprietà all'utente.
Eseguire l'override di IPropertyPageImpl::Apply
Quando gli utenti desiderano applicare le modifiche a oggetti, il sito della pagina delle proprietà chiamerà il metodo Applicare.Questo è il posto per eseguire l'operazione inversa del codice in Attiva — mentre Attiva richiesto valori dall'oggetto e li ha spinti i controlli nella pagina delle proprietà, Apply accetta valori dai controlli nella pagina delle proprietà e li inserisce nell'oggetto.
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;
}
[!NOTA]
Il controllo su m_bDirty all'inizio di questa implementazione è un controllo iniziale per evitare che gli aggiornamenti non necessari gli oggetti Apply se viene chiamato più volte.Sono inoltre disponibili controlli su ognuno dei valori della proprietà da assicurarsi che solo le modifiche possono generare una chiamata al metodo a Documento.
[!NOTA]
Espone FullName diDocumento come proprietà di sola lettura.Per aggiornare il nome file del documento in base alle modifiche apportate alla pagina delle proprietà, è necessario utilizzare il metodo Salva per salvare il file con un nome diverso.Pertanto, il codice in una pagina delle proprietà non deve limitarsi a ottenere o a impostare proprietà.
Visualizzare la pagina delle proprietà
Per visualizzare questa pagina, è necessario creare un oggetto di supporto semplice.L'oggetto supporto fornito un metodo che semplifica OleCreatePropertyFrame API per la visualizzazione di una singola pagina collegata a un singolo oggetto.Questo supporto è progettato per consentirne l'utilizzo da Visual Basic.
Utilizzare Aggiungere la finestra di dialogo della classe e Procedura guidata semplice ATL per generare una nuova classe e utilizzare Helper come nome breve.Una volta creato, aggiungere un metodo come illustrato nella tabella riportata di seguito.
Elemento |
Valore |
---|---|
Nome metodo |
ShowPage |
Parametri |
[in] BSTR bstrCaption, [in] BSTR bstrID, [in] IUnknown* pUnk |
Il parametro bstrCaption è la didascalia da visualizzare come titolo della finestra di dialogo.Il parametro bstrID è una stringa che rappresenta un CLSID o un ProgID della pagina delle proprietà da visualizzare.Il parametro pUnk sarà il puntatore IUnknown dell'oggetto le cui proprietà saranno configurate dalla pagina delle proprietà.
Implementare il metodo come illustrato di seguito:
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
);
}
Creare una macro
Dopo aver compilato il progetto, è possibile testare la pagina delle proprietà e l'oggetto helper utilizzando una macro semplice che è possibile creare e l'ambiente di sviluppo di Visual Studio.Questa macro viene creato un oggetto di supporto, quindi chiama il metodo ShowPage utilizzando il ProgID della pagina delle proprietà DocProperties e del puntatore IUnknown del documento attivo attualmente - l'editor di Visual Studio.Il codice necessario per questa macro viene indicato di seguito:
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
Quando si esegue questa macro, la pagina delle proprietà verrà visualizzato correntemente il nome file e lo stato di sola lettura al documento di testo attivo.Lo stato di sola lettura del documento riflette solo la possibilità di scrivere nel documento nell'ambiente di sviluppo, non influisce sull'attributo di sola lettura del file su disco.