Share via


Procédure pas à pas : hébergement de contenu WPF dans Win32

Windows Presentation Foundation (WPF) fournit un environnement riche pour la création d’applications. Toutefois, lorsque vous avez un investissement substantiel dans le code Win32, il peut être plus efficace d’ajouter des fonctionnalités WPF à votre application plutôt que de réécrire votre code d’origine. WPF fournit un mécanisme simple pour l’hébergement de contenu WPF dans une fenêtre Win32.

Ce tutoriel explique comment écrire un exemple d’application, hébergement de contenu WPF dans un exemple de fenêtre Win32, qui héberge du contenu WPF dans une fenêtre Win32. Vous pouvez étendre cet exemple pour héberger n’importe quelle fenêtre Win32. Étant donné qu’elle implique le mélange de code managé et non managé, l’application est écrite en C++/CLI.

Spécifications

Ce tutoriel suppose une connaissance de base de la programmation WPF et Win32. Pour une présentation de base de la programmation WPF, consultez Prise en main. Pour une introduction à la programmation Win32, vous devez référencer l’un des nombreux livres sur le sujet, en particulier Programmation Windows par Charles Petzold.

Étant donné que l’exemple qui accompagne ce didacticiel est implémenté dans C++/CLI, ce didacticiel suppose que l’utilisation de C++ permet de programmer l’API Windows, ainsi qu’une compréhension de la programmation de code managé. La connaissance de C++/CLI est utile, mais pas essentielle.

Remarque

Ce didacticiel comprend plusieurs exemples de code tirés de l'exemple associé. Cependant, pour une meilleure lecture, il n'inclut pas la totalité de l'exemple de code. Pour obtenir l’exemple de code complet, consultez Hébergement de contenu WPF dans un exemple de fenêtre Win32.

Procédure de base

Cette section décrit la procédure de base que vous utilisez pour héberger du contenu WPF dans une fenêtre Win32. Les sections restantes décrivent chaque étape dans les détails.

La clé permettant d’héberger du contenu WPF dans une fenêtre Win32 est la HwndSource classe. Cette classe encapsule le contenu WPF dans une fenêtre Win32, ce qui lui permet d’être incorporé dans votre interface utilisateur en tant que fenêtre enfant. L’approche suivante combine win32 et WPF dans une seule application.

  1. Implémentez votre contenu WPF en tant que classe managée.

  2. Implémentez une application Windows avec C++/CLI. Si vous commencez par une application existante et un code C++ non managé, vous pouvez généralement l’activer pour appeler du code managé en modifiant les paramètres de votre projet pour inclure l’indicateur du /clr compilateur.

  3. Affectez au modèle de thread un thread unique cloisonné (STA, Single-Threaded Apartment).

  4. Gérez la notification WM_CREATE dans votre procédure de fenêtre, puis effectuez les étapes suivantes :

    1. Créez un objet HwndSource en faisant de la fenêtre parente son paramètre parent.

    2. Créez une instance de votre classe de contenu WPF.

    3. Affectez une référence à l’objet de contenu WPF à la RootVisual propriété du HwndSource.

    4. Obtenez le HWND pour le contenu. La propriété Handle de l'objet HwndSource contient le handle de fenêtre (HWND). Pour obtenir un HWND que vous pouvez utiliser dans la partie non managée de l'application, effectuez un cast de Handle.ToPointer() en HWND.

  5. Implémentez une classe managée qui contient un champ statique pour contenir une référence à votre contenu WPF. Cette classe vous permet d’obtenir une référence au contenu WPF à partir de votre code Win32.

  6. Affectez le contenu WPF au champ statique.

  7. Recevez des notifications du contenu WPF en attachant un gestionnaire à un ou plusieurs des événements WPF.

  8. Communiquez avec le contenu WPF à l’aide de la référence que vous avez stockée dans le champ statique pour définir les propriétés, et ainsi de suite.

Remarque

Vous pouvez également utiliser du contenu WPF. Toutefois, vous devez le compiler séparément en tant que bibliothèque de liens dynamiques (DLL) et référencer cette DLL à partir de votre application Win32. Le reste de la procédure est similaire à celle présentée ci-dessus.

Implémentation de l'application hôte.

Cette section explique comment héberger du contenu WPF dans une application Win32 de base. Le contenu lui-même est implémenté en C++/CLI en tant que classe managée. Pour la plupart, il s’agit d’une programmation WPF simple. Les principaux aspects de l’implémentation de contenu sont décrits dans la section Implémentation du contenu WPF.

Application de base

Le point de départ de l’application hôte était de créer un modèle Visual Studio 2005.

  1. Ouvrez Visual Studio 2005, puis sélectionnez Nouveau projet dans le menu Fichier .

  2. Sélectionnez Win32 dans la liste des types de projets Visual C++. Si votre langue par défaut n’est pas C++, vous trouverez ces types de projets sous Autres langues.

  3. Sélectionnez un modèle Projet Win32, attribuez un nom au projet, puis cliquez sur OK pour lancer l’Assistant Application Win32.

  4. Acceptez les paramètres par défaut de l’Assistant, puis cliquez sur Terminer pour démarrer le projet.

Le modèle crée une application Win32 de base, notamment :

  • Un point d'entrée pour l'application

  • Une fenêtre avec une procédure de fenêtre associée (WndProc)

  • Menu avec les en-têtes Fichier et Aide . Le menu Fichier comporte un élément de sortie qui ferme l’application. Le menu Aide contient un élément À propos de qui lance une boîte de dialogue simple.

Avant de commencer à écrire du code pour héberger le contenu WPF, vous devez apporter deux modifications au modèle de base.

La première consiste à compiler le projet sous forme de code managé. Par défaut, le projet se compile sous forme de code non managé. Toutefois, étant donné que WPF est implémenté dans le code managé, le projet doit être compilé en conséquence.

  1. Cliquez avec le bouton droit sur le nom du projet dans l’Explorateur de solutions, puis sélectionnez Propriétés dans le menu contextuel pour lancer la boîte de dialogue Pages de propriétés.

  2. Sélectionnez Propriétés de configuration dans l’arborescence du volet gauche.

  3. Sélectionnez la prise en charge du Common Language Runtime dans la liste Paramètres par défaut du projet située dans le volet droit.

  4. Sélectionnez Prise en charge du Common Language Runtime (/clr) dans la zone de liste déroulante.

Remarque

L'indicateur de ce compilateur vous permet d'utiliser du code managé dans votre application, mais la compilation de votre code non managé se fera toujours comme avant.

WPF utilise le modèle de thread d’appartement à thread unique (STA). Pour fonctionner correctement avec le code de contenu WPF, vous devez définir le modèle de thread de l’application sur STA en appliquant un attribut au point d’entrée.

[System::STAThreadAttribute] //Needs to be an STA thread to play nicely with WPF
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{

Hébergement du contenu WPF

Le contenu WPF est une application d’entrée d’adresse simple. Elle est constituée de plusieurs contrôles TextBox destinés à recevoir le nom d'utilisateur, l'adresse et ainsi de suite. Il existe également deux Button contrôles, OK et Cancel. Lorsque l’utilisateur clique sur OK, le gestionnaire d’événements du Click bouton collecte les données des TextBox contrôles, l’affecte aux propriétés correspondantes et déclenche un événement personnalisé. OnButtonClicked Quand l’utilisateur clique sur Annuler, le gestionnaire déclenche simplement OnButtonClicked. L'objet d'argument d'événement pour OnButtonClicked contient un champ booléen qui indique le bouton sur lequel l'utilisateur a cliqué.

Le code permettant d’héberger le contenu WPF est implémenté dans un gestionnaire pour la notification WM_CREATE sur la fenêtre hôte.

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;

La GetHwnd méthode prend des informations de taille et de position, ainsi que le handle de fenêtre parent et retourne le handle de fenêtre du contenu WPF hébergé.

Remarque

Vous ne pouvez pas utiliser de directive #using pour l'espace de noms System::Windows::Interop. Cela entraîne une collision de noms entre la structure MSG de cet espace de noms et la structure MSG déclarée dans winuser.h. Vous devez à la place utiliser des noms qualifiés complets pour accéder au contenu de cet espace de noms.

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();
}

Vous ne pouvez pas héberger le contenu WPF directement dans la fenêtre de votre application. Au lieu de cela, vous créez d’abord un HwndSource objet pour encapsuler le contenu WPF. Cet objet est essentiellement une fenêtre conçue pour héberger un contenu WPF. Vous hébergez l’objet HwndSource dans la fenêtre parente en le créant en tant qu’enfant d’une fenêtre Win32 qui fait partie de votre application. Les HwndSource paramètres du constructeur contiennent beaucoup les mêmes informations que celles que vous transmettez à CreateWindow lorsque vous créez une fenêtre enfant Win32.

Vous créez ensuite une instance de l’objet de contenu WPF. Dans ce cas, le contenu WPF est implémenté en tant que classe distincte, WPFPageà l’aide de C++/CLI. Vous pouvez également implémenter le contenu WPF avec XAML. Toutefois, pour ce faire, vous devez configurer un projet distinct et générer le contenu WPF en tant que DLL. Vous pouvez ajouter une référence à cette DLL à votre projet et l’utiliser pour créer une instance du contenu WPF.

Vous affichez le contenu WPF dans votre fenêtre enfant en affectant une référence au contenu WPF à la RootVisual propriété de l’objet HwndSource.

La ligne de code suivante attache un gestionnaire d’événements, WPFButtonClickedà l’événement de contenu OnButtonClicked WPF. Ce gestionnaire est appelé quand l’utilisateur clique sur le bouton OK ou Annuler. Consultez la section Communication avec le contenu WPF pour plus d’informations sur ce gestionnaire d’événements.

La dernière ligne de code présentée retourne le handle de fenêtre (HWND) associé à l'objet HwndSource. Vous pouvez utiliser ce handle à partir de votre code Win32 pour envoyer des messages à la fenêtre hébergée, bien que l’exemple ne le fasse pas. L'objet HwndSource déclenche un événement chaque fois qu'il reçoit un message. Pour traiter les messages, appelez la méthode AddHook pour attacher un gestionnaire de messages et traiter ensuite les messages dans ce gestionnaire.

Stockage d'une référence au contenu WPF

Pour de nombreuses applications, vous souhaiterez communiquer avec le contenu WPF ultérieurement. Par exemple, vous pouvez modifier les propriétés de contenu WPF ou avoir peut-être l’objet HwndSource hôte de contenu WPF différent. Pour ce faire, vous avez besoin d’une référence à l’objet HwndSource ou au contenu WPF. L’objet HwndSource et son contenu WPF associé restent en mémoire jusqu’à ce que vous détruisiez le handle de fenêtre. Cependant, la variable que vous assignez à l'objet HwndSource sera hors de portée dès que vous retournerez de la procédure de fenêtre. La façon habituelle de gérer ce problème avec les applications Win32 consiste à utiliser une variable statique ou globale. Malheureusement, vous ne pouvez pas assigner un objet managé à ces types de variable. Vous pouvez assigner le handle de fenêtre associé à l'objet HwndSource à une variable globale ou statique, mais cela ne permet pas d'accéder à l'objet proprement dit.

La solution la plus simple à ce problème consiste à implémenter une classe managée qui contient un jeu de champs statiques pour stocker les références à tous les objets managés auxquels vous devez accéder. L’exemple utilise la WPFPageHost classe pour contenir une référence au contenu WPF, ainsi que les valeurs initiales d’un certain nombre de ses propriétés qui peuvent être modifiées ultérieurement par l’utilisateur. Cette option est définie dans l'en-tête.

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 dernière partie de la fonction GetHwnd assigne des valeurs à ces champs en vue d'une utilisation ultérieure pendant que myPage se trouve toujours dans la portée.

Communication avec le contenu WPF

Il existe deux types de communication avec le contenu WPF. L’application reçoit des informations du contenu WPF lorsque l’utilisateur clique sur les boutons OK ou Annuler . L’application dispose également d’une interface utilisateur qui permet à l’utilisateur de modifier différentes propriétés de contenu WPF, telles que la couleur d’arrière-plan ou la taille de police par défaut.

Comme mentionné ci-dessus, lorsque l’utilisateur clique sur l’un des deux boutons, le contenu WPF déclenche un OnButtonClicked événement. L'application attache un gestionnaire à cet événement pour recevoir ces notifications. Si le bouton OK a été cliqué, le gestionnaire obtient les informations utilisateur à partir du contenu WPF et l’affiche dans un ensemble de contrôles statiques.

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: ");
    }
}

Le gestionnaire reçoit un objet d’argument d’événement personnalisé du contenu WPF. MyPageEventArgs La propriété de l’objet IsOK est définie true sur si le bouton OK a été cliqué et false si le bouton Annuler a été cliqué.

Si le bouton OK a été cliqué, le gestionnaire obtient une référence au contenu WPF de la classe de conteneur. Il collecte ensuite les informations utilisateur détenues par les propriétés de contenu WPF associées et utilise les contrôles statiques pour afficher les informations sur la fenêtre parente. Étant donné que les données de contenu WPF sont sous la forme d’une chaîne managée, elles doivent être marshalées pour être utilisées par un contrôle Win32. Si l’utilisateur a cliqué sur le bouton Annuler, le gestionnaire efface les données des contrôles statiques.

L’interface utilisateur de l’application fournit un ensemble de cases d’option qui permettent à l’utilisateur de modifier la couleur d’arrière-plan du contenu WPF et plusieurs propriétés liées à la police. L'exemple suivant est un extrait de la procédure de fenêtre (WndProc) de l'application et de son traitement des messages qui définit différentes propriétés sur différents messages, notamment la couleur d'arrière-plan. Les autres sont similaires et ne sont pas illustrées. Consultez l'exemple complet pour plus de détails et pour connaître le contexte.

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;

Pour définir la couleur d’arrière-plan, obtenez une référence au contenu WPF (hostedPage) WPFPageHost et définissez la propriété de couleur d’arrière-plan sur la couleur appropriée. L'exemple utilise trois options de couleur : la couleur d'origine, du vert clair ou du saumon clair. La couleur d'arrière-plan d'origine est stockée en tant que champ statique dans la classe WPFPageHost. Pour définir les deux autres couleurs, vous devez créer un objet SolidColorBrush et transmettre au constructeur une valeur de couleur statique à partir de l'objet Colors.

Implémentation de la page WPF

Vous pouvez héberger et utiliser le contenu WPF sans connaître l’implémentation réelle. Si le contenu WPF avait été empaqueté dans une DLL distincte, il aurait pu être généré dans n’importe quel langage CLR (Common Language Runtime). Voici une brève procédure pas à pas de l’implémentation C++/CLI utilisée dans l’exemple. Cette section comprend les sous-sections suivantes.

Disposition

Les éléments d’interface utilisateur du contenu WPF se composent de cinq TextBox contrôles, avec les contrôles associés Label : Nom, Adresse, Ville, État et Zip. Il existe également deux Button contrôles, OK et Cancel

Le contenu WPF est implémenté dans la WPFPage classe. La disposition est gérée avec un élément de disposition Grid. La classe hérite de Grid, ce qui en fait l’élément racine du contenu WPF.

Le constructeur de contenu WPF prend la largeur et la hauteur requises, et la taille en Grid conséquence. Il définit ensuite la disposition de base en créant un ensemble d’objets ColumnDefinition et RowDefinition en les ajoutant à la Grid base ColumnDefinitions d’objets et RowDefinitions aux collections, respectivement. Une grille contenant cinq lignes et sept colonnes est ainsi définie et ses dimensions sont déterminées par le contenu des cellules.

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]);
  }

Ensuite, le constructeur ajoute les éléments d’interface utilisateur au Grid. Le premier élément est le texte du titre, qui est un contrôle Label centré dans la première ligne de la grille.

//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 ligne suivante contient le contrôle Label Name (nom) et le contrôle TextBox qui lui est associé. Comme le même code est utilisé pour chaque paire label/textbox, il est placé dans une paire de méthodes privées et est utilisé pour les cinq paires label/textbox. Les méthodes créent le contrôle approprié et appellent les méthodes statiques Grid et SetColumn de la classe SetRow pour placer les contrôles dans la bonne cellule. Une fois le contrôle créé, l'exemple appelle la méthode Add sur la propriété Children du Grid pour ajouter le contrôle à la grille. Le code permettant d'ajouter les paires label/texbox restantes est similaire. Consultez l'exemple de code pour plus d'informations.

//Add the Name Label and TextBox
nameLabel = CreateLabel(0, 1, "Name");
this->Children->Add(nameLabel);
nameTextBox = CreateTextBox(1, 1, 3);
this->Children->Add(nameTextBox);

Les deux méthodes sont implémentées comme suit :

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;
}

Enfin, l’exemple ajoute les boutons OK et Annuler et attache un gestionnaire d’événements à leurs Click événements.

//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);

Retour des données à la fenêtre hôte

Quand l'utilisateur clique sur l'un de ces boutons, l'événement Click correspondant est déclenché. La fenêtre hôte peut attacher simplement des gestionnaires à ces événements et obtenir directement les données des contrôles TextBox. L'exemple utilise une approche un peu moins directe. Il gère le Click contenu WPF, puis déclenche un événement OnButtonClickedpersonnalisé pour notifier le contenu WPF. Cela permet au contenu WPF d’effectuer une validation de paramètre avant de notifier l’hôte. Le gestionnaire obtient le texte des contrôles TextBox et l'assigne aux propriétés publiques, à partir desquelles l'hôte peut extraire les informations.

La déclaration event dans WPFPage.h :

public:
  delegate void ButtonClickHandler(Object ^, MyPageEventArgs ^);
  WPFPage();
  WPFPage(int height, int width);
  event ButtonClickHandler ^OnButtonClicked;

Le gestionnaire d'événements Click dans 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));
}

Définition des propriétés WPF

L’hôte Win32 permet à l’utilisateur de modifier plusieurs propriétés de contenu WPF. Du côté Win32, il s’agit simplement de modifier les propriétés. L’implémentation dans la classe de contenu WPF est un peu plus compliquée, car il n’existe aucune propriété globale unique qui contrôle les polices pour tous les contrôles. Au lieu de cela, la propriété appropriée de chaque contrôle est modifiée dans les accesseurs set des propriétés. L’exemple suivant montre le code de la DefaultFontFamily propriété. La définition de la propriété appelle une méthode privée qui, à son tour, définit les propriétés FontFamily de plusieurs contrôles.

À partir de WPFPage.h :

property FontFamily^ DefaultFontFamily
{
  FontFamily^ get() {return _defaultFontFamily;}
  void set(FontFamily^ value) {SetFontFamily(value);}
};

À partir de WPFPage.ccp :

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;
}

Voir aussi