Procedura dettagliata: hosting di contenuto WPF in Win32
Windows Presentation Foundation (WPF) fornisce un ambiente funzionale per la creazione di applicazioni. Tuttavia, se si utilizza una grande quantità di codice Win32, può essere più efficace aggiungere funzionalità WPF all'applicazione anziché riscrivere il codice originale. WPF fornisce un meccanismo semplice per l'hosting di contenuto WPF in una finestra Win32.
In questa esercitazione viene illustrato come scrivere un'applicazione di esempio, Esempio di hosting di un contenuto WPF in una finestra Win32 (la pagina potrebbe essere in inglese), che ospita contenuto WPF in una finestra Win32. L'esempio può essere esteso a qualsiasi finestra Win32. Dal momento che implica la combinazione di codice gestito e non gestito, l'applicazione viene scritta in C++/CLI.
Nel presente argomento sono contenute le seguenti sezioni.
- Requisiti
- Procedura di base
- Implementazione dell'applicazione host
- Implementazione della pagina WPF
- Argomenti correlati
Requisiti
Per questa esercitazione si presuppone una conoscenza di base della programmazione WPF e Win32. Per un'introduzione alla programmazione WPF, vedere Guida introduttiva (WPF). Per un'introduzione alla programmazione Win32, fare riferimento a uno dei numerosi manuali sull'argomento, in particolare Programming Windows di Charles Petzold.
Essendo l'esempio che accompagna questa esercitazione implementato in C++/CLI, si presuppone una buona conoscenza dell'utilizzo di C++ per la programmazione dell'API Win32, oltre alla conoscenza della programmazione in codice gestito. La conoscenza di C++/CLI è utile ma non essenziale.
![]() |
---|
In questa esercitazione sono inclusi diversi esempi di codice relativi all'esempio associato.Tuttavia, per una questione di leggibilità, il codice di esempio completo non è compreso.Per il codice di esempio completo, vedere Esempio di hosting di un contenuto WPF in una finestra Win32 (la pagina potrebbe essere in inglese). |
Procedura di base
In questa sezione viene illustrata la procedura di base utilizzata per ospitare contenuto WPF in una finestra Win32. Nelle sezioni restanti vengono illustrati i dettagli dei vari passaggi.
La chiave per ospitare contenuto WPF in una finestra Win32 è la classe HwndSource. Questa classe esegue il wrapping del contenuto WPF in una finestra Win32, consentendo di incorporarlo nell'user interface (UI) come finestra figlio. Nell'approccio illustrato di seguito Win32 e WPF sono combinati in un'unica applicazione.
Implementare il contenuto WPF come classe gestita.
Implementare un'applicazione Win32 con C++/CLI. Se si parte da un'applicazione esistente e da codice C++ non gestito, in genere è possibile abilitarla alla chiamata a codice gestito modificando le impostazioni del progetto e includendo il flag del compilatore /clr.
Impostare il modello di threading su apartment a thread singolo (STA).
Gestire la notifica WM_CREATE (la pagina potrebbe essere in inglese) nella routine della finestra ed eseguire le operazioni seguenti:
Creare un nuovo oggetto HwndSource con la finestra padre utilizzata come parametro parent.
Creare un'istanza della classe di contenuto WPF.
Assegnare alla proprietà RootVisual di HwndSource un riferimento all'oggetto contenuto WPF.
Ottenere HWND per il contenuto. La proprietà Handle dell'oggetto HwndSource contiene l'handle della finestra (HWND). Per ottenere HWND utilizzabile nella parte non gestita dell'applicazione, eseguire il cast di Handle.ToPointer() a HWND.
Implementare una classe gestita contenente un campo statico che a sua volta contiene 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 le notifiche dal contenuto WPF associando un gestore a uno o più eventi WPF.
Comunicare con il contenuto WPF utilizzando il riferimento archiviato nel campo statico per impostare le proprietà ed eseguire altre operazioni.
![]() |
---|
È anche possibile implementare il contenuto WPF mediante Extensible Application Markup Language (XAML).Tuttavia, sarà necessario compilarlo separatamente come dynamic-link library (DLL) e fare riferimento a tale DLL dall'applicazione Win32.La parte restante della procedura è simile a quella appena descritta. |
Implementazione dell'applicazione host
In questa sezione viene illustrato come ospitare contenuto WPF in un'applicazione Win32 di base. Il contenuto viene implementato in C++/CLI come classe gestita. In gran parte si tratta di semplice programmazione WPF. Gli aspetti principali dell'implementazione del contenuto vengono trattati in Implementazione del contenuto WPF.
Applicazione di base
Hosting del contenuto WPF
Riferimento al contenuto WPF
Comunicazione con il contenuto WPF
Applicazione di base
Il punto di partenza per l'applicazione host consisteva nella creazione di un modello in Microsoft 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 contenuti in Altri linguaggi.
Selezionare un modello Progetto Win32, assegnare un nome al progetto e scegliere OK per avviare la Creazione guidata applicazione Win32.
Accettare le impostazioni predefinite della procedura guidata e scegliere Fine per avviare il progetto.
Il modello crea un'applicazione Win32 di base che include quanto segue:
Un punto di ingresso per l'applicazione.
Una finestra, con una routine della finestra associata (WndProc).
Un menu dotato di intestazioni File e ?. Il menu File possiede un elemento Esci che consente di chiudere l'applicazione. Il menu ? possiede un elemento Informazioni su che consente di avviare una semplice finestra di dialogo.
Prima di iniziare a scrivere il codice per ospitare il contenuto WPF, è necessario apportare due modifiche al modello di base.
La prima modifica riguarda la compilazione del progetto come codice gestito. Per impostazione predefinita, il progetto viene compilato come codice non gestito. Tuttavia, dal momento che WPF è implementato in codice gestito, il progetto deve essere compilato di conseguenza.
Fare clic con il pulsante destro del mouse sul nome del progetto in Esplora soluzioni e selezionare Proprietà dal menu di scelta rapida per avviare la finestra di dialogo Pagine delle proprietà.
Selezionare Proprietà di configurazione dalla visualizzazione struttura ad albero nel riquadro di sinistra.
Selezionare il supporto Common Language Runtime dall'elenco Impostazioni predefinite progetto nel riquadro di destra.
Selezionare Supporto Common Language Runtime (/clr) dall'elenco a discesa.
![]() |
---|
Questo flag del compilatore consente di utilizzare codice gestito nell'applicazione, tuttavia la compilazione avverrà sempre mediante codice non gestito, come in precedenza. |
WPF utilizza il modello di threading STA (apartment a thread singolo). Per utilizzare correttamente 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 è una semplice applicazione di immissione dell'indirizzo. È costituito da diversi controlli TextBox nei quali immettere nome utente, indirizzo e così via. Sono inoltre presenti due controlli Button, OK e Cancel. Facendo clic su OK, il gestore eventi Click del pulsante raccoglie i dati dai controlli TextBox, li assegna alle proprietà corrispondenti e genera un evento personalizzato, OnButtonClicked. Facendo clic su Cancel, il gestore genera semplicemente OnButtonClicked. L'oggetto argomento dell'evento per OnButtonClicked contiene un campo booleano indicante il pulsante scelto.
Il codice di hosting del contenuto WPF viene implementato in un gestore per la notifica WM_CREATE (la pagina potrebbe essere in inglese) nella finestra host.
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 acquisisce informazioni sulla dimensione e posizione oltre all'handle della finestra padre e restituisce l'handle della finestra del contenuto WPF ospitato.
![]() |
---|
Non è possibile utilizzare una direttiva #using per lo spazio dei nomi System::Windows::Interop,in quanto si creerebbe un conflitto di nomi tra la struttura MSG nello spazio dei nomi e la struttura MSG dichiarata in winuser.h.Al contrario, occorre utilizzare nomi completi per accedere al contenuto dello 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 contenuto WPF direttamente nella finestra dell'applicazione. Al contrario, occorre prima creare un oggetto HwndSource per eseguire il wrapping del contenuto WPF. Questo oggetto è fondamentalmente una finestra progettata per ospitare un contenuto WPF. Per ospitare l'oggetto HwndSource nella finestra padre, occorre crearlo come figlio di una finestra Win32 appartenente all'applicazione. I parametri del costruttore HwndSource contengono pressoché le stesse informazioni che verrebbero passate a CreateWindow durante la creazione di una finestra figlio Win32.
La fase successiva prevede la creazione di un'istanza dell'oggetto contenuto WPF. In questo caso, il contenuto WPF viene implementato come classe separata, WPFPage, mediante C++/CLI. È anche possibile implementare il contenuto WPF mediante XAML. A tale scopo, tuttavia, è necessario configurare un progetto separato e compilare il contenuto WPF come DLL. È possibile aggiungere un riferimento al DLL nel progetto e utilizzarlo per creare un'istanza del contenuto WPF.
Per visualizzare il contenuto WPF nella finestra figlio, assegnare un riferimento al contenuto alla proprietà RootVisual di HwndSource.
La riga di codice successiva associa un gestore eventi, WPFButtonClicked, all'evento OnButtonClicked del contenuto WPF. Questo gestore viene chiamato quando l'utente fa clic sul pulsante OK o Cancel. Vedere Comunicazione con il contenuto WPF per ulteriori informazioni su questo gestore eventi.
La riga finale del codice illustrata restituisce l'handle della finestra (HWND) associato all'oggetto HwndSource. È possibile utilizzare questo handle dal codice Win32 per inviare messaggi alla finestra di hosting, benché questo non avvenga nell'esempio. L'oggetto HwndSource genera un evento ogni qualvolta riceve un messaggio. Per elaborare i messaggi, chiamare il metodo AddHook per associare un gestore di messaggi, quindi elaborare i messaggi in tale gestore.
Riferimento al contenuto WPF
Per molte applicazioni si vorrà comunicare con il contenuto WPF in un secondo momento. Ad esempio, sarà possibile modificare le proprietà del contenuto WPF o fare in modo che l'oggetto HwndSource ospiti un contenuto WPF diverso. A tal proposito, occorre un riferimento all'oggetto HwndSource o al contenuto WPF. L'oggetto HwndSource e il contenuto WPF associato restano in memoria fino all'eliminazione dell'handle della finestra. Tuttavia, la variabile assegnata all'oggetto HwndSource uscirà dall'ambito non appena si esce dalla routine della finestra. Per gestire questo problema con le applicazioni Win32 si utilizza di solito una variabile statica o globale. Sfortunatamente, non è possibile assegnare un oggetto gestito ai suddetti tipi di variabili. È possibile assegnare l'handle della finestra associato all'oggetto HwndSource a una variabile globale o statica, ma ciò non consentirà di accedere all'oggetto in questione.
La soluzione più semplice a questo problema consiste nell'implementare una classe gestita contenente un insieme di campi statici che a loro volta contengono i riferimenti agli oggetti gestiti ai quali si desidera accedere. Nell'esempio viene utilizzata la classe WPFPageHost, la quale contiene un riferimento al contenuto WPF oltre ai valori iniziali di diverse proprietà, modificabili in un secondo momento dall'utente. La classe viene definita 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 ai suddetti campi che verranno utilizzati in un secondo momento, con myPage ancora nell'ambito.
Comunicazione 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 Cancel. L'applicazione dispone anche di un'UI che consente di modificare diverse proprietà del contenuto WPF, ad esempio il colore di sfondo o le dimensioni del carattere predefinite.
Come indicato in precedenza, quando l'utente fa clic su uno dei pulsanti il contenuto WPF genera un evento OnButtonClicked. L'applicazione associa un gestore a questo evento per ricevere le notifiche. Nel caso sia stato scelto il pulsante OK, il gestore ottiene le informazioni utente dal contenuto WPF e le visualizza in un insieme di controlli statici.
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 dell'evento personalizzato dal contenuto WPF, MyPageEventArgs. La proprietà IsOK dell'oggetto è impostata su true se il pulsante scelto è OK, altrimenti su false se il pulsante scelto è Cancel.
Se il pulsante scelto è OK, il gestore ottiene un riferimento al contenuto WPF dalla classe dei contenitori. Raccoglie quindi le informazioni utente contenute nelle proprietà del contenuto WPF associate e utilizza i controlli statici per visualizzare le informazioni nella finestra padre. Essendo i dati del contenuto WPF sotto forma di stringa gestita, devono essere sottoposti a marshalling per l'utilizzo da parte di un controllo Win32. Se il pulsante scelto è Cancel, il gestore cancella i dati dai controlli statici.
L'UI dell'applicazione fornisce un insieme di pulsanti di opzione che consentono di modificare il colore di sfondo del contenuto WPF e diverse proprietà correlate al tipo di carattere. Nell'esempio seguente viene illustrato un estratto di routine della finestra (WndProc) dell'applicazione, nonché la gestione dei messaggi tramite la quale è possibile impostare varie proprietà in messaggi diversi, incluso il colore di sfondo. La parte restante è simile, pertanto non viene illustrata. Vedere l'esempio completo per i dettagli e il contesto.
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, ottenere un riferimento al contenuto WPF (hostedPage) da WPFPageHost e impostare la proprietà del colore di sfondo sul colore appropriato. Nell'esempio vengono utilizzate tre opzioni di colore: il colore originale, verde chiaro o salmone chiaro. Il colore di sfondo originale viene archiviato come campo statico nella classe WPFPageHost. Per impostare gli altri due colori, creare un nuovo oggetto SolidColorBrush e passare al costruttore un valore di colore statico dall'oggetto Colors.
Implementazione della pagina WPF
È possibile ospitare e utilizzare il contenuto WPF senza alcuna conoscenza dell'implementazione effettiva. Se il contenuto WPF fosse stato assemblato in un DLL separato, la compilazione sarebbe potuta avvenire in qualsiasi linguaggio common language runtime (CLR). Di seguito viene riportata una breve procedura dettagliata relativa all'implementazione C++/CLI utilizzata nell'esempio. Nella sezione sono contenute le seguenti sottosezioni.
Layout
Restituzione dei dati alla finestra host
Impostazione delle proprietà WPF
Layout
Gli elementi dell'UI nel contenuto WPF sono costituiti da cinque controlli TextBox, dotati di controlli Label associati: Name, Address, City, State e Zip. Sono inoltre presenti due controlli Button, OK e Cancel.
Il contenuto WPF viene implementato nella classe WPFPage. Il layout viene gestito mediante un apposito elemento Grid. La classe eredita da Grid, che la rende effettivamente l'elemento radice del contenuto WPF.
Il costruttore del contenuto WPF misura la larghezza e l'altezza richieste e sulla base di queste adatta le dimensioni di Grid. Definisce quindi il layout di base creando un insieme di oggetti ColumnDefinition e RowDefinition e aggiungendoli rispettivamente agli insiemi ColumnDefinitions e RowDefinitions di base dell'oggetto Grid. Viene così definita una griglia di cinque righe e sette colonne, le cui dimensioni sono 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]);
}
Successivamente il costruttore aggiunge gli elementi dell'UI a 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 Label Name e il controllo TextBox associato. Dal momento che per ogni coppia etichetta/casella di testo viene utilizzato lo stesso codice, questo viene collocato in una coppia di metodi privati e utilizzato per tutte e cinque le coppie etichetta/casella di testo. I metodi creano il controllo appropriato e chiamano i metodi SetColumn e SetRow statici della classe Grid per posizionare i controlli nella cella appropriata. Una volta creato il controllo, nell'esempio viene chiamato il metodo Add sulla proprietà Children di Grid per aggiungere il controllo alla griglia. Il codice utilizzato per aggiungere le coppie etichetta/casella di testo restanti è simile. Vedere il codice di esempio per i dettagli.
//Add the Name Label and TextBox
nameLabel = CreateLabel(0, 1, "Name");
this->Children->Add(nameLabel);
nameTextBox = CreateTextBox(1, 1, 3);
this->Children->Add(nameTextBox);
Di seguito viene riportata l'implementazione dei due metodi:
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, nell'esempio vengono aggiunti i pulsanti OK e Cancel e viene associato un gestore eventi agli eventi Click correlati.
//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
Facendo clic su un pulsante, viene generato il rispettivo evento Click. La finestra host potrebbe semplicemente associare i gestori a questi eventi e ottenere i dati direttamente dai controlli TextBox. Nell'esempio viene utilizzato un approccio meno diretto. Click viene gestito all'interno del contenuto WPF e un evento personalizzato OnButtonClicked viene generato per notificare il contenuto WPF. In questo modo il contenuto WPF può eseguire la convalida dei parametri prima di notificare l'host. Il gestore ottiene il testo dai controlli TextBox e lo assegna a proprietà pubbliche, dalle quali l'host può 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 di Win32, si tratta semplicemente di modificare le proprietà. L'implementazione nella classe del contenuto WPF è leggermente più complessa, poiché non esiste un'unica proprietà globale che controlla i tipi di carattere per tutti i controlli. Al contrario, la proprietà adatta per ogni controllo viene modificata nelle funzioni di accesso dell'insieme di proprietà. Nell'esempio che segue viene illustrato il codice per la proprietà DefaultFontFamily. Impostando la proprietà, viene chiamato 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;
}