Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Windows Presentation Foundation (WPF) offre un ambiente avanzato per la creazione di applicazioni. Tuttavia, quando si ha un notevole investimento nel codice Win32, potrebbe essere più efficace aggiungere funzionalità WPF all'applicazione invece di riscrivere il codice originale. WPF offre un meccanismo semplice per l'hosting di contenuto WPF in una finestra Win32.
Questa esercitazione descrive come scrivere un'applicazione di esempio, Hosting WPF in una finestra Win32 - Applicazione di esempio, che ospita contenuto WPF in una finestra Win32. È possibile estendere questo esempio per ospitare qualsiasi finestra Win32. Poiché prevede la combinazione di codice gestito e non gestito, l'applicazione viene scritta in C++/CLI.
Requisiti
Questa esercitazione presuppone una familiarità di base con la programmazione WPF e Win32. Per un'introduzione di base alla programmazione WPF, vedere Introduzione. Per un'introduzione alla programmazione Win32, devi fare riferimento a uno dei numerosi libri sul tema, in particolare Programmazione di Windows di Charles Petzold.
Poiché l'esempio che accompagna questa esercitazione viene implementato in C++/CLI, questa esercitazione presuppone familiarità con l'uso di C++ per programmare l'API Windows e una conoscenza della programmazione del codice gestito. La familiarità con C++/CLI è utile ma non essenziale.
Nota
Questa esercitazione include diversi esempi di codice dell'esempio associato. Tuttavia, per la leggibilità, non include il codice di esempio completo. Per il codice di esempio completo, vedere Hosting di contenuto WPF in un esempio di finestra Win32.
Procedura di base
Questa sezione descrive la procedura di base usata per ospitare contenuto WPF in una finestra Win32. Le sezioni rimanenti illustrano i dettagli di ogni passaggio.
La chiave per ospitare contenuto WPF in una finestra Win32 è la classe HwndSource. Questa classe incapsula il contenuto WPF in una finestra Win32, permettendogli di essere incorporato nell'interfaccia come finestra figlia. L'approccio seguente combina Win32 e WPF in una singola applicazione.
Implementa il contenuto WPF come classe gestita.
Implementare un'applicazione Windows con C++/CLI. Se si inizia con un'applicazione esistente e un codice C++ non gestito, in genere è possibile abilitarlo per chiamare il codice gestito modificando le impostazioni del progetto in modo da includere il flag del compilatore
/clr
.Impostare il modello di threading su appartamento a thread singolo (STA).
Gestisci la notifica WM_CREATEnella procedura della finestra ed esegui le operazioni seguenti:
Creare un nuovo oggetto HwndSource con la finestra padre come parametro
parent
.Crea un'istanza della classe di contenuto WPF.
Assegnare alla proprietà RootVisual del HwndSourceun riferimento all'oggetto di contenuto WPF.
Ottenere l'HWND del contenuto. La proprietà Handle dell'oggetto HwndSource contiene l'handle di finestra (HWND). Per ottenere un HWND che è possibile usare nella parte non gestita dell'applicazione, eseguire il cast di
Handle.ToPointer()
in un HWND.
Implementare una classe gestita che contiene un campo statico per contenere un riferimento al contenuto WPF. Questa classe consente di ottenere un riferimento al contenuto WPF dal codice Win32.
Assegnare il contenuto WPF al campo statico.
Ricevere notifiche dal contenuto WPF collegando un gestore a uno o più eventi WPF.
Comunicare con il contenuto WPF usando il riferimento archiviato nel campo statico per impostare le proprietà e così via.
Nota
È anche possibile usare il contenuto WPF. Tuttavia, dovrai compilarlo separatamente come libreria a collegamento dinamico (DLL) e fare riferimento a tale DLL dall'applicazione Win32. Il resto della procedura è simile a quello descritto in precedenza.
Implementazione dell'applicazione host
Questa sezione descrive come ospitare contenuto WPF in un'applicazione Win32 di base. Il contenuto stesso viene implementato in C++/CLI come classe gestita. Per la maggior parte, è semplice programmazione WPF. Gli aspetti principali dell'implementazione del contenuto sono descritti in Implementazione del contenuto WPF.
Applicazione di base
Il punto di partenza per l'applicazione host consiste nel creare un modello di Visual Studio 2005.
Aprire Visual Studio 2005 e selezionare Nuovo Progetto dal menu File.
Selezionare Win32 dall'elenco dei tipi di progetto Visual C++. Se il linguaggio predefinito non è C++, questi tipi di progetto sono disponibili in altri linguaggi.
Selezionare un modello Progetto Win32, assegnare un nome al progetto e fare clic su OK per avviare la Creazione guidata per applicazioni Win32.
Accettare le impostazioni predefinite della procedura guidata e quindi cliccare su Fine per avviare il progetto.
Il modello crea un'applicazione Win32 di base, tra cui:
Punto di ingresso per l'applicazione.
Finestra, con una procedura finestra associata (WndProc).
Menu con le intestazioni File e Guida. Il menu File include un elemento Esci che chiude l'applicazione. Il menu Aiuto include un elemento 'Informazioni' che avvia una finestra di dialogo semplice.
Prima di iniziare a scrivere codice per ospitare il contenuto WPF, è necessario apportare due modifiche al modello di base.
Il primo consiste nel compilare il progetto come codice gestito. Per impostazione predefinita, il progetto viene compilato come codice non gestito. Tuttavia, poiché WPF viene implementato nel codice gestito, il progetto deve essere compilato di conseguenza.
Fare clic destro sul nome del progetto in Esplora soluzioni e scegliere Proprietà dal menu di scelta rapida per avviare la finestra di dialogo Pagine delle proprietà.
Selezionare Proprietà di configurazione dalla visualizzazione albero nel riquadro sinistro.
Selezionare Supporto per il Common Language Runtime dall'elenco Predefiniti del progetto nel riquadro destro.
Selezionare Common Language Runtime Support (/clr) nella casella di riepilogo a discesa.
Nota
Questo flag del compilatore consente di usare il codice gestito nell'applicazione, ma il codice non gestito verrà comunque compilato come prima.
WPF utilizza il modello di threading a singolo thread di tipo STA (Single-Threaded Apartment). Per funzionare correttamente con il codice del contenuto WPF, è necessario impostare il modello di threading dell'applicazione su STA applicando un attributo al punto di ingresso.
[System::STAThreadAttribute] //Needs to be an STA thread to play nicely with WPF
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
Hosting del contenuto WPF
Il contenuto WPF è un'applicazione di immissione di indirizzi semplice. È costituito da diversi controlli TextBox per inserire il nome utente, l'indirizzo e così via. Sono disponibili anche due controlli Button, OK e Cancel. Quando l'utente fa clic su OK, il gestore eventi Click del pulsante raccoglie i dati dai controlli TextBox, lo assegna alle proprietà corrispondenti e genera un evento personalizzato OnButtonClicked
. Quando l'utente fa clic su Annulla, il gestore si limita a sollevare OnButtonClicked
. L'oggetto argomento dell'evento per OnButtonClicked
contiene un campo booleano che indica quale pulsante è stato cliccato.
Il codice per ospitare il contenuto WPF viene implementato in un gestore per la notifica di WM_CREATE nella finestra ospitante.
case WM_CREATE :
GetClientRect(hWnd, &rect);
wpfHwnd = GetHwnd(hWnd, rect.right-375, 0, 375, 250);
CreateDataDisplay(hWnd, 275, rect.right-375, 375);
CreateRadioButtons(hWnd);
break;
Il metodo GetHwnd
accetta informazioni sulle dimensioni e sulla posizione più l'handle della finestra padre e restituisce l'handle della finestra del contenuto WPF ospitato.
Nota
Non è possibile usare una direttiva #using
per lo spazio dei nomi System::Windows::Interop
. In questo modo viene creato un conflitto di nomi tra la struttura MSG nello spazio dei nomi e la struttura MSG dichiarata in winuser.h. È invece necessario usare nomi completamente qualificati per accedere al contenuto di tale spazio dei nomi.
HWND GetHwnd(HWND parent, int x, int y, int width, int height)
{
System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters(
"hi" // NAME
);
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD; // style
System::Windows::Interop::HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
WPFPage ^myPage = gcnew WPFPage(width, height);
//Assign a reference to the WPF page and a set of UI properties to a set of static properties in a class
//that is designed for that purpose.
WPFPageHost::hostedPage = myPage;
WPFPageHost::initBackBrush = myPage->Background;
WPFPageHost::initFontFamily = myPage->DefaultFontFamily;
WPFPageHost::initFontSize = myPage->DefaultFontSize;
WPFPageHost::initFontStyle = myPage->DefaultFontStyle;
WPFPageHost::initFontWeight = myPage->DefaultFontWeight;
WPFPageHost::initForeBrush = myPage->DefaultForeBrush;
myPage->OnButtonClicked += gcnew WPFPage::ButtonClickHandler(WPFButtonClicked);
source->RootVisual = myPage;
return (HWND) source->Handle.ToPointer();
}
Non è possibile ospitare il contenuto WPF direttamente nella finestra dell'applicazione. Invece, innanzitutto si crea un oggetto HwndSource per avvolgere il contenuto WPF. Questo oggetto è fondamentalmente una finestra progettata per ospitare un contenuto WPF. L'oggetto HwndSource viene ospitato nella finestra padre creandolo come figlio di una finestra Win32 che fa parte dell'applicazione. I parametri del costruttore HwndSource contengono informazioni simili a quelle che si passerebbero a CreateWindow quando si crea una finestra figlia Win32.
Creare quindi un'istanza dell'oggetto di contenuto WPF. In questo caso, il contenuto WPF viene implementato come classe separata, WPFPage
, usando C++/CLI. È anche possibile implementare il contenuto WPF con XAML. A tale scopo, tuttavia, è necessario configurare un progetto separato e compilare il contenuto WPF come DLL. È possibile aggiungere un riferimento a tale DLL al progetto e usarlo per creare un'istanza del contenuto WPF.
Il contenuto WPF viene visualizzato nella finestra figlia assegnando un riferimento al contenuto WPF alla proprietà RootVisual del HwndSource.
La riga di codice successiva associa un gestore eventi, WPFButtonClicked
, all'evento del contenuto WPF OnButtonClicked
. Questo gestore viene chiamato quando l'utente fa clic sul pulsante OK o Annulla. Per un'ulteriore discussione su questo gestore di eventi, vedere il contenuto communicating_with_the_WPF.
La riga finale di codice visualizzata restituisce l'handle di finestra (HWND) associato all'oggetto HwndSource. Puoi usare questo handle dal codice Win32 per inviare messaggi alla finestra ospitata, anche se l'esempio non lo fa. L'oggetto HwndSource genera un evento ogni volta che riceve un messaggio. Per elaborare i messaggi, chiamare il metodo AddHook per allegare un gestore di messaggi e quindi elaborare i messaggi in tale gestore.
Conservazione di un riferimento al contenuto WPF
Per molte applicazioni, sarà necessario comunicare con il contenuto WPF in un secondo momento. Ad esempio, potrebbe essere necessario modificare le proprietà del contenuto WPF oppure fare in modo che l'oggetto HwndSource ospiti diversi contenuti WPF. A tale scopo, è necessario un riferimento all'oggetto HwndSource o al contenuto WPF. L'oggetto HwndSource e il relativo contenuto WPF associato rimangono in memoria fino a quando non si elimina l'handle della finestra. Tuttavia, la variabile assegnata all'oggetto HwndSource esce dall'ambito non appena si torna dalla routine della finestra. Il modo personalizzato per gestire questo problema con le applicazioni Win32 consiste nell'usare una variabile statica o globale. Sfortunatamente, non è possibile assegnare un oggetto gestito a tali tipi di variabili. È possibile assegnare l'handle di finestra associato all'oggetto HwndSource a una variabile globale o statica, ma ciò non fornisce l'accesso all'oggetto stesso.
La soluzione più semplice per questo problema consiste nell'implementare una classe gestita che contiene un set di campi statici per contenere riferimenti a qualsiasi oggetto gestito a cui è necessario accedere. Nell'esempio viene utilizzata la classe WPFPageHost
per contenere un riferimento al contenuto WPF, oltre ai valori iniziali di una serie di proprietà che potrebbero essere modificate in un secondo momento dall'utente. Questo è definito nell'intestazione.
public ref class WPFPageHost
{
public:
WPFPageHost();
static WPFPage^ hostedPage;
//initial property settings
static System::Windows::Media::Brush^ initBackBrush;
static System::Windows::Media::Brush^ initForeBrush;
static System::Windows::Media::FontFamily^ initFontFamily;
static System::Windows::FontStyle initFontStyle;
static System::Windows::FontWeight initFontWeight;
static double initFontSize;
};
La seconda parte della funzione GetHwnd
assegna valori a tali campi per un uso successivo mentre myPage
è ancora nell'ambito.
Interagire con il contenuto WPF
Esistono due tipi di comunicazione con il contenuto WPF. L'applicazione riceve informazioni dal contenuto WPF quando l'utente fa clic sui pulsanti OK o Annulla. L'applicazione ha anche un'interfaccia utente che consente all'utente di modificare varie proprietà del contenuto WPF, ad esempio il colore di sfondo o le dimensioni predefinite del carattere.
Come accennato in precedenza, quando l'utente fa clic su uno dei pulsanti il contenuto WPF genera un evento OnButtonClicked
. L'applicazione collega un gestore a questo evento per ricevere queste notifiche. Se è stato fatto clic sul pulsante OK
void WPFButtonClicked(Object ^sender, MyPageEventArgs ^args)
{
if(args->IsOK) //display data if OK button was clicked
{
WPFPage ^myPage = WPFPageHost::hostedPage;
LPCWSTR userName = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Name: " + myPage->EnteredName).ToPointer();
SetWindowText(nameLabel, userName);
LPCWSTR userAddress = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Address: " + myPage->EnteredAddress).ToPointer();
SetWindowText(addressLabel, userAddress);
LPCWSTR userCity = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("City: " + myPage->EnteredCity).ToPointer();
SetWindowText(cityLabel, userCity);
LPCWSTR userState = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("State: " + myPage->EnteredState).ToPointer();
SetWindowText(stateLabel, userState);
LPCWSTR userZip = (LPCWSTR) InteropServices::Marshal::StringToHGlobalAuto("Zip: " + myPage->EnteredZip).ToPointer();
SetWindowText(zipLabel, userZip);
}
else
{
SetWindowText(nameLabel, L"Name: ");
SetWindowText(addressLabel, L"Address: ");
SetWindowText(cityLabel, L"City: ");
SetWindowText(stateLabel, L"State: ");
SetWindowText(zipLabel, L"Zip: ");
}
}
Il gestore riceve un oggetto argomento evento personalizzato dal contenuto WPF, MyPageEventArgs
. La proprietà
Se è stato fatto clic sul pulsante OK, il gestore ottiene un riferimento al contenuto WPF dalla classe contenitore. Raccoglie quindi le informazioni utente contenute nelle proprietà del contenuto WPF associate e usa i controlli statici per visualizzare le informazioni nella finestra padre. Poiché i dati del contenuto WPF sono sotto forma di stringa gestita, è necessario effettuare il marshalling per l'uso da parte di un controllo Win32. Se è stato fatto clic sul pulsante Annulla, il gestore cancella i dati dai controlli statici.
L'interfaccia utente dell'applicazione fornisce un set di pulsanti di opzione che consentono all'utente di modificare il colore di sfondo del contenuto WPF e diverse proprietà correlate al tipo di carattere. L'esempio seguente è un estratto della routine della finestra dell'applicazione (WndProc) e della relativa gestione dei messaggi che imposta varie proprietà su messaggi diversi, incluso il colore di sfondo. Gli altri sono simili e non vengono visualizzati. Per informazioni dettagliate e contesto, vedere l'esempio completo.
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
//Menu selections
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
//RadioButtons
case IDC_ORIGINALBACKGROUND :
WPFPageHost::hostedPage->Background = WPFPageHost::initBackBrush;
break;
case IDC_LIGHTGREENBACKGROUND :
WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightGreen);
break;
case IDC_LIGHTSALMONBACKGROUND :
WPFPageHost::hostedPage->Background = gcnew SolidColorBrush(Colors::LightSalmon);
break;
Per impostare il colore di sfondo, ottieni un riferimento al contenuto WPF (hostedPage
) da WPFPageHost
e imposta la proprietà del colore di sfondo sul colore appropriato. L'esempio usa tre opzioni di colore: il colore originale, il verde chiaro o il salmone chiaro. Il colore di sfondo originale viene archiviato come campo statico nella classe WPFPageHost
. Per impostare le altre due, creare un nuovo oggetto SolidColorBrush e passare al costruttore un valore di colori statici dall'oggetto Colors.
Implementazione della pagina WPF
È possibile ospitare e usare il contenuto WPF senza alcuna conoscenza dell'implementazione effettiva. Se il contenuto WPF era stato incluso in una DLL separata, potrebbe essere stato compilato in qualsiasi linguaggio CLR (Common Language Runtime). Di seguito è riportata una breve procedura dettagliata dell'implementazione di C++/CLI usata nell'esempio. Questa sezione contiene le sottosezioni seguenti.
Impaginazione
Gli elementi dell'interfaccia utente nel contenuto WPF sono costituiti da cinque controlli TextBox, con i controlli Label associati: Name, Address, City, State e Zip. Sono disponibili anche due controlli Button, OK e Cancel
Il contenuto WPF viene implementato nella classe WPFPage
. Il layout viene gestito con un elemento di layout Grid. La classe eredita da Grid, che la rende effettivamente l'elemento radice del contenuto WPF.
Il costruttore di contenuto WPF accetta la larghezza e l'altezza necessarie e ridimensiona il Grid di conseguenza. Definisce quindi il layout di base creando un set di oggetti ColumnDefinition e RowDefinition e aggiungendoli rispettivamente agli insiemi ColumnDefinitions e RowDefinitions della base di oggetti Grid. In questo modo viene definita una griglia di cinque righe e sette colonne, con le dimensioni determinate dal contenuto delle celle.
WPFPage::WPFPage(int allottedWidth, int allotedHeight)
{
array<ColumnDefinition ^> ^ columnDef = gcnew array<ColumnDefinition ^> (4);
array<RowDefinition ^> ^ rowDef = gcnew array<RowDefinition ^> (6);
this->Height = allotedHeight;
this->Width = allottedWidth;
this->Background = gcnew SolidColorBrush(Colors::LightGray);
//Set up the Grid's row and column definitions
for(int i=0; i<4; i++)
{
columnDef[i] = gcnew ColumnDefinition();
columnDef[i]->Width = GridLength(1, GridUnitType::Auto);
this->ColumnDefinitions->Add(columnDef[i]);
}
for(int i=0; i<6; i++)
{
rowDef[i] = gcnew RowDefinition();
rowDef[i]->Height = GridLength(1, GridUnitType::Auto);
this->RowDefinitions->Add(rowDef[i]);
}
Il costruttore aggiunge quindi gli elementi dell'interfaccia utente al Grid. Il primo elemento è il testo del titolo, ovvero un controllo Label centrato nella prima riga della griglia.
//Add the title
titleText = gcnew Label();
titleText->Content = "Simple WPF Control";
titleText->HorizontalAlignment = System::Windows::HorizontalAlignment::Center;
titleText->Margin = Thickness(10, 5, 10, 0);
titleText->FontWeight = FontWeights::Bold;
titleText->FontSize = 14;
Grid::SetColumn(titleText, 0);
Grid::SetRow(titleText, 0);
Grid::SetColumnSpan(titleText, 4);
this->Children->Add(titleText);
La riga successiva contiene il controllo Name Label e il relativo controllo TextBox associato. Poiché lo stesso codice viene usato per ogni coppia di etichette/caselle di testo, viene inserito in una coppia di metodi privati e usato per tutte e cinque le coppie etichetta/casella di testo. I metodi creano il controllo appropriato e chiamano i metodi statici SetColumn e SetRow della classe Grid per posizionare i controlli nella cella appropriata. Dopo aver creato il controllo, l'esempio chiama il metodo Add sulla proprietà Children del Grid per aggiungere il controllo alla griglia. Il codice per aggiungere le coppie di etichette/caselle di testo rimanenti è simile. Per informazioni dettagliate, vedere il codice di esempio.
//Add the Name Label and TextBox
nameLabel = CreateLabel(0, 1, "Name");
this->Children->Add(nameLabel);
nameTextBox = CreateTextBox(1, 1, 3);
this->Children->Add(nameTextBox);
L'implementazione dei due metodi è la seguente:
Label ^WPFPage::CreateLabel(int column, int row, String ^ text)
{
Label ^ newLabel = gcnew Label();
newLabel->Content = text;
newLabel->Margin = Thickness(10, 5, 10, 0);
newLabel->FontWeight = FontWeights::Normal;
newLabel->FontSize = 12;
Grid::SetColumn(newLabel, column);
Grid::SetRow(newLabel, row);
return newLabel;
}
TextBox ^WPFPage::CreateTextBox(int column, int row, int span)
{
TextBox ^newTextBox = gcnew TextBox();
newTextBox->Margin = Thickness(10, 5, 10, 0);
Grid::SetColumn(newTextBox, column);
Grid::SetRow(newTextBox, row);
Grid::SetColumnSpan(newTextBox, span);
return newTextBox;
}
Infine, l'esempio aggiunge i pulsanti di OK e Cancel e associa un gestore eventi agli eventi Click.
//Add the Buttons and atttach event handlers
okButton = CreateButton(0, 5, "OK");
cancelButton = CreateButton(1, 5, "Cancel");
this->Children->Add(okButton);
this->Children->Add(cancelButton);
okButton->Click += gcnew RoutedEventHandler(this, &WPFPage::ButtonClicked);
cancelButton->Click += gcnew RoutedEventHandler(this, &WPFPage::ButtonClicked);
Restituzione dei dati alla finestra host
Quando si fa clic su uno dei due pulsanti, viene generato il relativo evento Click. La finestra host può semplicemente associare i gestori a questi eventi e ottenere i dati direttamente dai controlli TextBox. L'esempio usa un approccio leggermente meno diretto. Gestisce il Click all'interno del contenuto WPF e quindi attiva un evento personalizzato OnButtonClicked
, per notificare il contenuto WPF. In questo modo, il contenuto WPF può eseguire una convalida dei parametri prima di inviare una notifica all'host. Il gestore prima ottiene il testo dai controlli TextBox e poi lo assegna alle proprietà pubbliche, da cui l'host può successivamente recuperare le informazioni.
Dichiarazione di evento, in WPFPage.h:
public:
delegate void ButtonClickHandler(Object ^, MyPageEventArgs ^);
WPFPage();
WPFPage(int height, int width);
event ButtonClickHandler ^OnButtonClicked;
Gestore eventi Click, in WPFPage.cpp:
void WPFPage::ButtonClicked(Object ^sender, RoutedEventArgs ^args)
{
//TODO: validate input data
bool okClicked = true;
if(sender == cancelButton)
okClicked = false;
EnteredName = nameTextBox->Text;
EnteredAddress = addressTextBox->Text;
EnteredCity = cityTextBox->Text;
EnteredState = stateTextBox->Text;
EnteredZip = zipTextBox->Text;
OnButtonClicked(this, gcnew MyPageEventArgs(okClicked));
}
Impostazione delle proprietà WPF
L'host Win32 consente all'utente di modificare diverse proprietà del contenuto WPF. Dal lato Win32, è semplicemente una questione di modifica delle proprietà. L'implementazione nella classe di contenuto WPF è leggermente più complessa, perché non esiste una singola proprietà globale che controlla i tipi di carattere per tutti i controlli. Al contrario, la proprietà appropriata per ogni controllo viene modificata nelle funzioni di accesso del set di proprietà. Nell'esempio seguente viene illustrato il codice per la proprietà DefaultFontFamily
. Impostare la proprietà richiama un metodo privato che, a sua volta, imposta le proprietà FontFamily per i vari controlli.
Da WPFPage.h:
property FontFamily^ DefaultFontFamily
{
FontFamily^ get() {return _defaultFontFamily;}
void set(FontFamily^ value) {SetFontFamily(value);}
};
Da WPFPage.cpp:
void WPFPage::SetFontFamily(FontFamily^ newFontFamily)
{
_defaultFontFamily = newFontFamily;
titleText->FontFamily = newFontFamily;
nameLabel->FontFamily = newFontFamily;
addressLabel->FontFamily = newFontFamily;
cityLabel->FontFamily = newFontFamily;
stateLabel->FontFamily = newFontFamily;
zipLabel->FontFamily = newFontFamily;
}
Vedere anche
.NET Desktop feedback