Compartir a través de


Tutorial: Hospedar contenido de WPF en Win32

Windows Presentation Foundation (WPF) proporciona un entorno enriquecido para crear aplicaciones. Sin embargo, cuando ya se tiene una inversión sustancial en código de Win32, puede ser más eficaz agregar la 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 WPF en una ventana Win32.

Este tutorial describe cómo escribir una aplicación de ejemplo, Hosting WPF Content in a Win32 Window Sample, que hospeda contenido WPF en una ventana Win32. Puede extender este ejemplo para hospedar cualquier ventana Win32. Dado que implica la mezcla de código administrado y no administrado, la aplicación se escribe en C++/CLI.

Este tema contiene las secciones siguientes.

  • Requisitos
  • El procedimiento básico
  • Implementar la aplicación host
  • Implementar la página WPF
  • Temas relacionados

Requisitos

En este tutorial se da por hecho que está familiarizado con la programación básica en WPF y Win32. Para obtener una introducción básica a la programación en WPF, vea Introducción (WPF). Para obtener una introducción a la programación en Win32, puede consultar cualquiera de los numerosos libros sobre el tema, en particular Programming Windows escrito por Charles Petzold.

Dado que el ejemplo que acompaña este tutorial se implementa en C++/CLI, este tutorial asume que se conoce el uso de C++ para programar la API de Win32 y que se conoce la programación de código administrado. El conocimiento de C++/CLI es útil, pero no esencial.

NotaNota

En este tutorial se incluyen varios ejemplos de código del ejemplo asociado.Sin embargo, para facilitar la legibilidad, no se incluye el código de ejemplo completo.Para obtener el ejemplo de código completo, vea Hosting WPF Content in a Win32 Window Sample.

El procedimiento básico

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

La clave para hospedar contenido WPF en una ventana Win32 es la clase HwndSource. Esta clase envuelve el contenido WPF en una ventana de Win32, lo que permite incorporarlo a la user interface (UI) como una ventana secundaria. El enfoque siguiente combina Win32 y WPF en una aplicación única.

  1. Implemente el contenido WPF como una clase administrada.

  2. Implemente una aplicación Win32 con C++/CLI. Si está empezando con una aplicación existente y código C++ no administrado. normalmente podrá habilitarlo para que llame a código adeministrado cambiando la configuración del proyecto para que incluya el marcador del compilador /clr.

  3. Establezca el modelo de subprocesos en apartamento de un único subproceso (STA).

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

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

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

    3. Asigne una referencia al objeto de contenido WPF a la propiedad RootVisual del objeto HwndSource.

    4. Obtenga el HWND para el contenido. La propiedad Handle del objeto HwndSource contiene el identificador de la ventana (HWND). Para obtener un HWND que pueda utilizar 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 con una referencia al contenido WPF. Esta clase permite obtener una referencia al contenido WPF desde el código Win32.

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

  7. Para recibir notificaciones del contenido WPF, adjunte un identificador a uno o más de los eventos de WPF.

  8. Para comunicar con el contenido WPF, utilice la referencia almacenada en el campo estático para establecer propiedades y así sucesivamente.

NotaNota

También puede utilizar Extensible Application Markup Language (XAML) para implementar el contenido WPF.No obstante, tendrá que compilarlo separadamente como una dynamic-link library (DLL) y hacer referencia a esa DLL desde la aplicación Win32.El resto del procedimiento es similar al perfilado anteriormente.

Implementar la aplicación host

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

  • Aplicación básica

  • Hospedar el contenido WPF

  • Mantener una referencia al contenido WPF

  • Comunicar con el contenido WPF

Aplicación básica

El punto inicial para la aplicación host fue crear una plantilla Microsoft 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 Visual C++. Si el lenguaje predeterminado no es C++, encontrará estos tipos de proyecto bajo Otros lenguajes.

  3. Seleccione una plantilla 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, que incluye:

  • Un punto de entrada para la aplicación.

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

  • Un menú con los encabezados Archivo y Ayuda. El menú Archivo tiene un elemento Salir que cierra la aplicación. El menú Ayuda tiene un elemento Acerca de que inicia un cuadro de diálogo simple.

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

La primera es 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 estar compilado en consecuencia.

  1. Haga clic con el botón secundario del mouse en el nombre de 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 de la izquierda.

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

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

NotaNota

Este marcador del compilador permite utilizar código administrado en la aplicación, pero el código no administrado continuará compilándose como antes.

WPF utiliza el modelo de subprocesos en apartamento de un único subproceso (STA). Para trabajar correctamente con el código de contenido 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 WPF

El contenido WPF es una aplicación de entrada de dirección simple. Está compuesto de varios controles TextBox que aceptan el nombre de usuario, la dirección, etc. También hay dos controles Button, Aceptar y Cancelar. Cuando el usuario hace clic en Aceptar, el controlador del evento Click del botón recopila los datos de los controles TextBox, los asigna a las propiedades correspondientes y produce un evento personalizado, OnButtonClicked. Cuando el usuario hace clic en Cancelar, el controlador simplemente produce 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 WPF se implementa en un controlador para la notificación 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 método GetHwnd acepta la información de tamaño y de posición, más el identificador de la ventana primaria y devuelve el identificador de ventana del contenido WPF hospedado.

NotaNota

No se puede utilizar una directiva #using para el espacio de nombres System::Windows::Interop.Si se hace así, se crea un conflicto de nombres entre la estructura MSG de ese espacio de nombres y la estructura MSG declarada en winuser.h.En su lugar, debe utilizar nombres completos para tener acceso 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 directamente el contenido WPF en la ventana de la aplicación. En su lugar, cree primero un objeto HwndSource para envolver el contenido WPF. Este objeto es básicamente una ventana diseñada para hospedar un contenido WPF. Para hospedar el objeto HwndSource en la ventana primaria, créelo como un elemento secundario de una ventana Win32 que forma parte de la aplicación. Los parámetros de constructor de HwndSource contienen más o menos la misma información que se pasaría a CreateWindow para crear una ventana secundaria de Win32.

A continuación, cree una instancia del objeto de contenido WPF. En este caso, el contenido WPF se implementa como una clase independiente, WPFPage, utilizando C++/CLI. También podría implementar el contenido WPF con XAML. No obstante, para hacerlo deberá preparar un proyecto independiente y generar el contenido WPF como una DLL. Puede agregar al proyecto una referencia a DLL y utilizar esa referencia para crear una instancia del contenido WPF.

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

La siguiente línea de código adjunta un controlador de evento, WPFButtonClicked, al evento OnButtonClicked del contenido WPF. Se llama a este controlador cuando el usuario hace clic en el botón Aceptar o Cancelar. Vea Comunicar con el contenido WPF para ver una explicación más extensa de este controlador de eventos.

La línea final del código que se muestra devuelve el identificador de ventana (HWND) está asociado al objeto HwndSource. Puede utilizar este controlador desde el código de Win32 para enviar mensajes a la ventana hospedada, aunque el ejemplo no lo hace. El objeto HwndSource provoca un evento cada vez que recibe un mensaje. Para procesar los mensajes, llame al método AddHook para asociar un controlador de mensajes y, a continuación, procese los mensajes en ese controlador.

Mantener una referencia al contenido WPF

Para muchas aplicaciones, deseará comunicar más tarde con el contenido WPF. Por ejemplo, quizá desee modificar las propiedades del contenido WPF o, quizás, hacer que el objeto HwndSource hospede diferente contenido WPF. Para ello, necesita una referencia al objeto HwndSource o al contenido WPF. El objeto HwndSource y su contenido WPF asociado permanecen en la memoria hasta que se destruya el identificador de ventana. Sin embargo, la variable que asigne al objeto HwndSource saldrá del ámbito tan pronto como vuelva del procedimiento de la ventana. La forma habitual de afrontar este problema con las aplicaciones Win32 consiste en utilizar una variable estática o global. Desgraciadamente, no se puede asignar un objeto administrado a esos tipos de variable. Puede asignar el identificador de ventana asociado al objeto HwndSource a una variable global o estática, pero eso no proporciona acceso al propio objeto.

La solución más simple 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 necesite tener acceso. El ejemplo utiliza la clase WPFPageHost para contener una referencia al contenido WPF, más los valores iniciales de varias de sus propiedades que, más tarde, podría cambiar el usuario. 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 función GetHwnd asigna valores a esos campos para su uso posterior mientras myPage esté todavía en ámbito.

Comunicar con el contenido WPF

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

Como antes se mencionó, cuando el usuario hace clic en cualquiera de los botones, el contenido WPF provoca un evento OnButtonClicked. La aplicación asocia 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 WPF y lo 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 WPF, MyPageEventArgs. La propiedad IsOK del objeto se establece en true si se hizo clic en el botón Aceptar y en false si se hizo clic en el botón Cancelar.

Si se hizo clic en el botón Aceptar, el controlador recibe una referencia al contenido WPF desde la clase contenedora. A continuación, recopila la información sobre el usuario que contienen las propiedades del contenido WPF y utiliza los controles estáticos para mostrar la información sobre la ventana primaria. Dado que los datos del contenido WPF adoptan la forma de una cadena administrada, un control Win32 debe calcular sus referencias para utilizarlos. Si se hizo clic en el botón Cancelar, el controlador borra los datos de los controles estáticos.

La UI de la aplicación proporciona un conjunto de botones de radio que permiten al usuario modificar el color de fondo del contenido WPF, así como varias propiedades relacionadas con la fuente. El ejemplo siguiente es un extracto del procedimiento de la ventana de la aplicación (WndProc) y de su control de mensajes que establece varias propiedades en diferentes mensajes, incluido el color de fondo. Los demás son similares y no se muestran. Vea el ejemplo completo para ver los detalles y el 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 WPF (hostedPage) desde WPFPageHost y establezca la propiedad de color de fondo en el color adecuado. El ejemplo utiliza tres opciones de color: el color original, verde claro o salmón claro. El color de fondo original se almacena en un campo estático en la clase WPFPageHost. Para establecer los otros dos, crea un nuevo objeto SolidColorBrush y pasa al constructor un valor de colores estático desde el objeto Colors.

Implementar la página WPF

Puede hospedar y utilizar el contenido WPF sin ningún conocimiento de la implementación real. Si el contenido WPF se hubiera empaquetado en una DLL independiente, podría haberse generado en cualquier lenguaje common language runtime (CLR). A continuación hay un breve tutorial de la implementación C++/CLI que se utiliza en el ejemplo. Esta sección contiene las subsecciones siguientes.

  • Diseño

  • Devolver los datos a la ventana host

  • Establecer las propiedades de WPF

Diseño

Los elementos de la UI del contenido WPF constan de cinco controles TextBox, con controles Label asociados: Name, Address, City, State y Zip. También hay dos controles Button, Aceptar y Cancelar.

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

El constructor de contenido WPF acepta el ancho y alto necesarios, y ajusta en consecuencia el elemento Grid. A continuación, define el diseño básico creando un conjunto de objetos ColumnDefinition y RowDefinition y los agrega a las colecciones base ColumnDefinitions y RowDefinitions del objeto Grid, 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 UI al objeto Grid. El primer elemento es el texto del título, que es un control Label centrado en la primera fila de la cuadrícula.

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

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

Finalmente, el ejemplo agrega los botones Aceptar y Cancelar, y asocia un controlador de evento a sus eventos 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);

Devolver los datos a la ventana host

Cuando se hace clic en cualquiera de los botones, se provoca su evento Click. La ventana host podría asociar simplemente los controladores a estos eventos y obtener directamente los datos de los controles TextBox. El ejemplo utiliza un enfoque algo menos directo. Administra Click dentro del contenido WPF y, a continuación, provoca un evento OnButtonClicked personalizado, para notificar al contenido WPF. Esto permite que el contenido WPF haga algunas validaciones de parámetros antes de notificar al host. El controlador obtiene el texto de los controles TextBox y lo asigna a propiedades públicas, de las que el host puede recuperar la información.

La declaración de evento, en WPFPage.h:

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

El controlador del evento Click, 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 WPF. Del lado de Win32, es simplemente una cuestión de cambiar las propiedades. La implementación de la clase de contenido WPF es algo más complicada, porque no hay ninguna propiedad global única que controle las fuentes para todos los controles. En su lugar, se modifica la propiedad correspondiente para cada control en los descriptores de acceso set de las propiedades. En el ejemplo siguiente se muestra el código para la propiedad DefaultFontFamily. Al establecer la propiedad se llama a un método privado que, a su vez establece las propiedades FontFamily para los diversos 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;
}

Vea también

Referencia

HwndSource

Conceptos

Interoperabilidad de WPF y Win32