Compartir a través de


Tutorial: Hospedaje de contenido de WPF en Win32

Windows Presentation Foundation (WPF) proporciona un entorno enriquecido para crear aplicaciones. Sin embargo, cuando tiene una inversión sustancial en el código Win32, puede ser más eficaz agregar funcionalidad de WPF a la aplicación en lugar de volver a escribir el código original. WPF proporciona un mecanismo sencillo para hospedar contenido de WPF en una ventana win32.

En este tutorial se describe cómo escribir una aplicación de ejemplo, hospedar contenido de WPF en un ejemplo de ventana win32, que hospeda el contenido de WPF en una ventana win32. Puede ampliar este ejemplo para hospedar cualquier ventana win32. Dado que implica mezclar código administrado y no administrado, la aplicación se escribe en C++/CLI.

Requisitos

En este tutorial se presupone una familiaridad básica con la programación de WPF y Win32. Para obtener una introducción básica a la programación de WPF, consulte Introducción. Para obtener una introducción a la programación Win32, debes consultar cualquiera de los numerosos libros sobre el tema, en particular Programación Windows de Charles Petzold.

Dado que el ejemplo que acompaña a este tutorial se implementa en C++/CLI, en este tutorial se supone que está familiarizado con el uso de C++ para programar la API de Windows, además de comprender la programación de código administrado. La familiaridad con C++/CLI es útil, pero no esencial.

Nota:

En este tutorial se incluyen varios ejemplos de código del ejemplo asociado. Sin embargo, para mejorar la legibilidad, no incluye el código de ejemplo completo. Para obtener el código de ejemplo completo, consulte Hospedaje de contenido de WPF en un ejemplo de ventana win32.

Procedimiento básico

En esta sección se describe el procedimiento básico que se usa para hospedar contenido de WPF en una ventana win32. En las secciones restantes se explican los detalles de cada paso.

La clave para hospedar contenido de WPF en una ventana win32 es la HwndSource clase . Esta clase ajusta el contenido de WPF en una ventana win32, lo que permite incorporarlo a la interfaz de usuario (UI) como una ventana secundaria. El siguiente enfoque combina Win32 y WPF en una sola aplicación.

  1. Implemente el contenido de WPF como una clase administrada.

  2. Implemente una aplicación de Windows con C++/CLI. Si empieza con una aplicación existente y código de C++ no administrado, normalmente puede habilitarlo para llamar al código administrado cambiando la configuración del proyecto para incluir la marca del /clr compilador.

  3. Establezca el modelo de subprocesos en apartamento de un solo hilo (STA).

  4. Gestione la notificación WM_CREATE en el procedimiento de ventana y realice lo siguiente:

    1. Cree un nuevo HwndSource objeto con la ventana primaria como parámetro parent .

    2. Cree una instancia de la clase de contenido de WPF.

    3. Asigne una referencia al objeto de contenido WPF a la propiedad de RootVisualHwndSource.

    4. Consiga el HWND del contenido. La Handle propiedad del HwndSource objeto contiene el identificador de ventana (HWND). Para obtener un HWND que puede usar en la parte no administrada de la aplicación, convierta Handle.ToPointer() en un HWND.

  5. Implemente una clase administrada que contenga un campo estático para contener una referencia al contenido de WPF. Esta clase permite obtener una referencia al contenido de WPF del código Win32.

  6. Asigne el contenido de WPF al campo estático.

  7. Reciba notificaciones del contenido de WPF adjuntando un controlador a uno o varios de los eventos de WPF.

  8. Comuníquese con el contenido de WPF usando la referencia que ha almacenado en el campo estático para configurar propiedades y realizar otras acciones.

Nota:

También puede usar contenido de WPF. Sin embargo, tendrá que compilarlo por separado como una biblioteca de enlace dinámico (DLL) y referenciar esa DLL desde la aplicación Win32. El resto del procedimiento es similar al descrito anteriormente.

Implementación de la aplicación host

En esta sección se describe cómo hospedar contenido de WPF en una aplicación Básica de Win32. El propio contenido se implementa en C++/CLI como una clase administrada. En su mayor parte, es una programación de WPF sencilla. Los aspectos clave de la implementación de contenido se describen en Implementación del contenido de WPF.

La aplicación básica

El punto de partida de la aplicación host era crear una plantilla de Visual Studio 2005.

  1. Abra Visual Studio 2005 y seleccione Nuevo proyecto en el menú Archivo .

  2. Seleccione Win32 en la lista de tipos de proyecto de Visual C++. Si el lenguaje predeterminado no es C++, encontrará estos tipos de proyecto en Otros lenguajes.

  3. Seleccione una plantilla de proyecto win32 , asigne un nombre al proyecto y haga clic en Aceptar para iniciar el Asistente para aplicaciones Win32.

  4. Acepte la configuración predeterminada del asistente y haga clic en Finalizar para iniciar el proyecto.

La plantilla crea una aplicación Win32 básica, entre las que se incluyen:

  • Un punto de entrada para la aplicación.

  • Una ventana, con un procedimiento de ventana asociado (WndProc).

  • Menú con encabezados Archivo y Ayuda . El menú Archivo tiene un elemento Exit que cierra la aplicación. El menú Ayuda tiene un elemento Acerca de que inicia un cuadro de diálogo sencillo.

Antes de empezar a escribir código para hospedar el contenido de WPF, debe realizar dos modificaciones en la plantilla básica.

La primera consiste en compilar el proyecto como código administrado. De forma predeterminada, el proyecto se compila como código no administrado. Sin embargo, dado que WPF se implementa en código administrado, el proyecto debe compilarse en consecuencia.

  1. Haga clic con el botón derecho en el nombre del proyecto en el Explorador de soluciones y seleccione Propiedades en el menú contextual para iniciar el cuadro de diálogo Páginas de propiedades .

  2. Seleccione Propiedades de configuración en la vista de árbol en el panel izquierdo.

  3. Seleccione Compatibilidad con Common Language Runtime en la lista Valores predeterminados del proyecto en el panel derecho.

  4. Seleccione Common Language Runtime Support (/clr) en el cuadro de lista desplegable.

Nota:

Esta marca del compilador permite usar código administrado en la aplicación, pero el código no administrado se compilará como antes.

WPF usa el modelo de hilos de apartamento de un único subproceso (STA). Para funcionar correctamente con el código de contenido de WPF, debe establecer el modelo de subprocesos de la aplicación en STA aplicando un atributo al punto de entrada.

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

Hospedar el contenido de WPF

El contenido de WPF es una aplicación de entrada de dirección simple. Consta de varios TextBox controles para tomar el nombre de usuario, la dirección, etc. También hay dos Button controles, Ok y Cancel. Cuando el usuario hace clic en Aceptar, el controlador de eventos del Click botón recopila los datos de los TextBox controles, los asigna a las propiedades correspondientes y genera un evento personalizado, OnButtonClicked. Cuando el usuario hace clic en Cancelar, el controlador simplemente genera OnButtonClicked. El objeto de argumento de evento para OnButtonClicked contiene un campo booleano que indica en qué botón se hizo clic.

El código para hospedar el contenido de WPF se implementa en un controlador para la notificación de WM_CREATE en la ventana 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;

El GetHwnd método toma información de tamaño y posición más el identificador de ventana principal y devuelve el identificador de ventana del contenido de WPF hospedado.

Nota:

No se puede usar una #using directiva para el System::Windows::Interop espacio de nombres. Al hacerlo, se crea una colisión de nombres entre la MSG estructura de ese espacio de nombres y la estructura MSG declarada en winuser.h. En su lugar, debe usar nombres completamente calificados para acceder al contenido de ese espacio de nombres.

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

No se puede hospedar el contenido de WPF directamente en la ventana de la aplicación. En su lugar, primero se crea un HwndSource objeto para encapsular el contenido de WPF. Este objeto es básicamente una ventana diseñada para hospedar un contenido de WPF. Hospedas el objeto HwndSource en la ventana principal creándolo como un elemento secundario de una ventana Win32 que forma parte de tu aplicación. Los HwndSource parámetros del constructor contienen la misma información que se pasaría a CreateWindow al crear una ventana secundaria de Win32.

A continuación, creará una instancia del objeto de contenido WPF. En este caso, el contenido de WPF se implementa como una clase independiente, WPFPage, mediante C++/CLI. También puedes implementar el contenido de WPF con XAML. Sin embargo, para ello, debe configurar un proyecto independiente y compilar el contenido de WPF como un archivo DLL. Puede agregar una referencia a ese archivo DLL al proyecto y usar esa referencia para crear una instancia del contenido de WPF.

Para mostrar el contenido de WPF en la ventana secundaria, asigne una referencia al contenido de WPF a la RootVisual propiedad de HwndSource.

La siguiente línea de código adjunta un controlador de eventos, WPFButtonClicked, al evento de contenido OnButtonClicked de WPF. Se llama a este controlador cuando el usuario hace clic en el botón Aceptar o Cancelar . Consulte communicating_with_the_WPF contenido para obtener más información sobre este controlador de eventos.

La última línea de código que se muestra devuelve el identificador de ventana (HWND) asociado al HwndSource objeto . Puedes usar este identificador desde el código Win32 para enviar mensajes a la ventana hospedada, aunque el ejemplo no lo hace. El HwndSource objeto genera un evento cada vez que recibe un mensaje. Para procesar los mensajes, llame al AddHook método para adjuntar un controlador de mensajes y, a continuación, procese los mensajes de ese controlador.

Mantener una referencia al contenido de WPF

Para muchas aplicaciones, querrá comunicarse con el contenido de WPF más adelante. Por ejemplo, es posible que desee modificar las propiedades de contenido de WPF o quizás tener el HwndSource objeto hospedando contenido WPF diferente. Para ello, necesita una referencia al objeto o al HwndSource contenido de WPF. El HwndSource objeto y su contenido de WPF asociado permanecen en memoria hasta que se destruye el identificador de ventana. Sin embargo, la variable que asigne al HwndSource objeto quedará fuera del ámbito en cuanto vuelva del procedimiento de ventana. La manera habitual de controlar este problema con las aplicaciones Win32 es usar una variable estática o global. Desafortunadamente, no se puede asignar un objeto administrado a esos tipos de variables. Puede asignar el identificador de ventana asociado con HwndSource el objeto a una variable global o estática, pero que no proporcione acceso al propio objeto.

La solución más sencilla a este problema es implementar una clase administrada que contiene un conjunto de campos estáticos para contener referencias a los objetos administrados a los que necesita acceso. En el ejemplo se usa la WPFPageHost clase para contener una referencia al contenido de WPF, además de los valores iniciales de una serie de sus propiedades que el usuario podría cambiar más adelante. Esto se define en el encabezado .

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 última parte de la GetHwnd función asigna valores a esos campos para su uso posterior mientras myPage todavía está en el ámbito.

Comunicación con el contenido de WPF

Hay dos tipos de comunicación con el contenido de WPF. La aplicación recibe información del contenido de WPF cuando el usuario hace clic en los botones Aceptar o Cancelar . La aplicación también tiene una interfaz de usuario que permite al usuario cambiar varias propiedades de contenido de WPF, como el color de fondo o el tamaño de fuente predeterminado.

Como se mencionó anteriormente, cuando el usuario hace clic en cualquiera de los botones, el contenido de WPF genera un OnButtonClicked evento. La aplicación adjunta un controlador a este evento para recibir estas notificaciones. Si se hizo clic en el botón Aceptar , el controlador obtiene la información del usuario del contenido de WPF y la muestra en un conjunto de controles estáticos.

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

El controlador recibe un objeto de argumento de evento personalizado del contenido de WPF, MyPageEventArgs. La propiedad del IsOK objeto se establece en true si se hizo clic en el botón Aceptar y false si se hizo clic en el botón Cancelar .

Si se hizo clic en el botón Aceptar , el controlador obtiene una referencia al contenido de WPF de la clase contenedora. A continuación, recopila la información de usuario que mantiene las propiedades de contenido de WPF asociadas y usa los controles estáticos para mostrar la información en la ventana primaria. Dado que los datos de contenido de WPF están en forma de una cadena administrada, se deben preparar para su transferencia por un control Win32. Si se hizo clic en el botón Cancelar , el controlador borra los datos de los controles estáticos.

La interfaz de usuario de la aplicación proporciona un conjunto de botones de radio que permiten al usuario modificar el color de fondo del contenido de WPF y varias propiedades relacionadas con fuentes. El ejemplo siguiente es un extracto del procedimiento de ventana de la aplicación (WndProc) y su control de mensajes que establece varias propiedades en mensajes diferentes, incluido el color de fondo. Los demás son similares y no se muestran. Consulte el ejemplo completo para obtener detalles y contexto.

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;

Para establecer el color de fondo, obtenga una referencia al contenido de WPF (hostedPage) de WPFPageHost y establezca la propiedad color de fondo en el color adecuado. En la muestra se usan tres opciones de color: el color original, el verde claro o el salmón claro. El color de fondo original se almacena como un campo estático en la WPFPageHost clase . Para establecer los otros dos, cree un nuevo SolidColorBrush objeto y pase al constructor un valor de colores estáticos del Colors objeto .

Implementación de la página WPF

Puede hospedar y usar el contenido de WPF sin ningún conocimiento de la implementación real. Si el contenido de WPF se había empaquetado en un archivo DLL independiente, podría haberse compilado en cualquier lenguaje de Common Language Runtime (CLR). A continuación se muestra un breve tutorial de la implementación de C++/CLI que se usa en el ejemplo. Esta sección contiene las siguientes subsecciones.

Diseño

Los elementos de la interfaz de usuario del contenido de WPF constan de cinco TextBox controles, con controles asociados Label : Nombre, Dirección, Ciudad, Estado y Zip. También hay dos Button controles, Ok y Cancel

El contenido de WPF se implementa en la WPFPage clase . El diseño se controla con un elemento de diseño Grid. La clase hereda de Grid, que lo convierte eficazmente en el elemento raíz de contenido de WPF.

El constructor de contenido de WPF toma el ancho y el alto necesarios, y ajusta el Grid tamaño en consecuencia. A continuación, define el diseño básico creando un conjunto de ColumnDefinition objetos y RowDefinition y agregándolos a la Grid base ColumnDefinitions de objetos y RowDefinitions colecciones, respectivamente. Esto define una cuadrícula de cinco filas y siete columnas, con las dimensiones determinadas por el contenido de las celdas.

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

A continuación, el constructor agrega los elementos de la interfaz de usuario a .Grid El primer elemento es el texto del título, que es un control Label centrado en la primera fila de la rejilla.

//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 siguiente fila contiene el control Name Label y su control asociado TextBox . Dado que se usa el mismo código para cada par de etiqueta/cuadro de texto, se coloca en un par de métodos privados y se usa para los cinco pares de etiquetas y cuadros de texto. Los métodos crean el control adecuado y llaman a los métodos estáticos de la clase GridSetColumn y SetRow para colocar los controles en la celda adecuada. Una vez creado el control, el ejemplo llama al Add método en la Children propiedad de Grid para agregar el control a la cuadrícula. El código para agregar los pares restantes de etiqueta o cuadro de texto es similar. Consulte el código de ejemplo para obtener más información.

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

La implementación de los dos métodos es la siguiente:

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

Por último, el ejemplo agrega los botones Aceptar y Cancelar y adjunta un controlador de eventos a sus Click eventos.

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

Devolver los datos a la ventana host

Cuando se hace clic en cualquiera de los botones, se genera el evento correspondiente Click. La ventana anfitriona podría simplemente asignar controladores a estos eventos y obtener los datos directamente de los controles TextBox. En el ejemplo se usa un enfoque algo menos directo. Controla el Click dentro del contenido de WPF y, a continuación, genera un evento personalizado OnButtonClicked para notificar al contenido de WPF. Esto permite que el contenido de WPF realice alguna validación de parámetros antes de notificar al host. El controlador obtiene el texto de los TextBox controles y lo asigna a las propiedades públicas, desde las que el host puede recuperar la información.

Declaración de evento, en WPFPage.h:

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

Controlador Click de eventos, en 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));
}

Establecer las propiedades de WPF

El host win32 permite al usuario cambiar varias propiedades de contenido de WPF. Desde el lado Win32, es simplemente cuestión de cambiar las propiedades. La implementación en la clase de contenido de WPF es algo más complicada, ya que no hay ninguna propiedad global única que controle las fuentes de todos los controles. En su lugar, se cambia la propiedad adecuada para cada control en los descriptores de acceso del conjunto de propiedades. En el ejemplo siguiente se muestra el código de la DefaultFontFamily propiedad . Al establecer la propiedad, se llama a un método privado que, a su vez, establece las propiedades FontFamily de los distintos controles.

Desde WPFPage.h:

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

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

Consulte también