Creación de una aplicación "Hola mundo" Aplicación para UWP en C++/CX
Importante
Este tutorial usa C++/CX. Microsoft ha lanzado C ++ / WinRT: una proyección de lenguaje C ++ 17 moderna completamente estándar para las API de Windows Runtime (WinRT). Para obtener más información sobre este lenguaje, consulte C++/WinRT.
Con Microsoft Visual Studio, puede usar C++/CX para desarrollar una aplicación que se ejecute en Windows con una interfaz de usuario definida en Extensible Application Markup Language (XAML).
Nota
En este tutorial se usa Visual Studio Community 2019. Si usa otra versión de Visual Studio, es posible que tenga una apariencia un poco diferente.
Antes de empezar
- Para completar este tutorial, debe usar Visual Studio Community, o una de las versiones que no son de la comunidad de Visual Studio, en un ordenador que ejecute Windows. Para su descarga, consulta Obtener las herramientas
- Para poder continuar, debe tener conocimientos básico de C++/CX, XAML y estar familiarizado con los conceptos que se detallan en la introducción a XAML.
- Para seguir, debe usar el diseño de ventana predeterminado en Visual Studio. Para restablecer el diseño predeterminado, en la barra de menús, elige Ventana>Restablecer diseño de la ventana.
Comparación de aplicaciones de escritorio de C++ con aplicaciones para UWP
Si viene de un segundo plano en la programación de escritorio de Windows en C++, probablemente encontrará que algunos aspectos de la escritura de aplicaciones para el UWP son familiares, pero otros aspectos requieren cierto aprendizaje.
¿Qué es igual?
Puede usar el STL, el CRT (con algunas excepciones) y cualquier otra biblioteca de C++ siempre y cuando el código solo llame a las funciones de Windows a las que se puede acceder desde el ambiente de tiempo de ejecución de Windows.
Si está acostumbrado a las superficies de diseñadores visuales, puede seguir usando el diseñador integrado en Microsoft Visual Studio o puede usar Blend for Visual Studio, que es una herramienta más completa. Si está acostumbrado a codificar la interfaz de usuario a mano, puede codificar a mano su XAML.
Sigues creando aplicaciones que usan tipos de sistemas operativos Windows y tus propios tipos personalizados.
Continúas usando el depurador, generador de perfiles y otras herramientas de desarrollo de Visual Studio.
Sigues creando aplicaciones que se compilan en el código máquina nativo mediante el compilador de Visual C++. Las aplicaciones para UWP en C ++ / CX no se ejecutan en un ambiente de tiempo de ejecución administrado.
Novedades
Los principios de diseño para las aplicaciones para UWP son muy distintos de los principios para las aplicaciones de escritorio. Se quita énfasis a los bordes, etiquetas, cuadros de diálogo, etc. de las ventanas. El contenido es lo más importante. Las grandes aplicaciones para UWP incorporan estos principios desde el comienzo de la etapa de planeación.
Toda la interfaz de usuario se define con XAML. La separación entre la interfaz de usuario y la lógica de programa principal es mucho más clara en una aplicación para UWP que en una aplicación de MFC o Win32. Puede haber otras personas trabajando en la apariencia de la interfaz de usuario en el archivo XAML mientras tú trabajas en el comportamiento en el archivo de código.
Estás programando principalmente con una API nueva, fácil de navegar y orientada a objetos, Windows en tiempo de ejecución, aunque Win32 sigue estando disponible en los dispositivos de Windows para realizar algunas funciones.
Usas C++/CX para consumir y crear objetos de Windows en tiempo de ejecución. C++/CX permite controlar excepciones de C++, admite delegados y eventos, y permite realizar recuentos automáticos de referencias de objetos creados en forma dinámica. Cuando usas C++/CX, los detalles del COM subyacente y de la arquitectura de Windows están ocultos en el código de aplicación. Para obtener más información, consulta la referencia de lenguaje de C++/CX.
La aplicación se compila en un paquete que también contiene metadatos sobre los tipos que incluye la aplicación, los recursos que usa y las funcionalidades que necesita (acceso a los archivos, acceso a Internet, acceso a la cámara, etc.).
En Microsoft Store y la Store de Windows Phone, su aplicación se verifica como segura mediante un proceso de certificación y se pueda ser reconocible a millones de clientes potenciales.
La aplicación Hello World Store en C ++ / CX
Nuestra primera aplicación es una presentación para el mundo ("Hello World") que demuestra algunas características básicas de interactividad, diseño y estilos. Vamos a crear una aplicación desde la plantilla de proyecto de aplicación universal de Windows. Si has desarrollado aplicaciones para Windows 8.1 y Windows Phone 8.1 antes, probablemente recuerdes que debes tener tres proyectos en Visual Studio, uno para la aplicación de Windows, otro para la aplicación de teléfono y otro con código compartido. La Plataforma universal de Windows (UWP) hace posible tener solo un proyecto que se ejecute en todos los dispositivos, incluidos los equipos de escritorio y portátiles que ejecutan Windows, dispositivos como tabletas, teléfonos móviles, dispositivos de VR, etc.
Empezaremos por los conceptos básicos:
Cómo crear un proyecto universal de Windows en Visual Studio.
Cómo comprender los proyectos y los archivos que se crean.
Cómo comprender las extensiones de componentes de Visual C++ (C++/CX) y cuándo usarlas.
Lo primero: crear una solución en Visual Studio
En la barra de menús de Visual Studio, elige Archivo>Nuevo>Proyecto... .
En el cuadro de diálogo Crear un nuevo proyecto, selecciona Aplicación en blanco (Universal Windows - C++/CX) . (Si no ves estas opciones, asegúrese de tener instaladas las herramientas de desarrollo de las aplicaciones universales de Windows. Consulta Configurar para obtener más información.
Elige Siguiente y escriba un nombre para el proyecto. Lo llamaremos HelloWorld.
Elige el botón Crear.
Nota
Si es la primera vez que usa Visual Studio, es posible que se le solicite habilitar el Modo desarrollador en el diálogo de configuración. El modo de desarrollador es una opción de configuración especial que habilita determinadas funciones, como permiso para ejecutar aplicaciones directamente, en lugar de solo desde la Store. Para obtener más información, lea Habilitar el dispositivo para el desarrollo. Para continuar con esta guía, selecciona Modo de desarrollador, haz clic en Sí y cierra el cuadro de diálogo.
Se crean los archivos del proyecto.
Antes de continuar, veamos qué hay en la solución.
Sobre los archivos de proyecto
Cada archivo .xaml de una carpeta de proyecto tiene asociados un archivo .xaml.h y otro archivo .xaml.cpp en la misma carpeta, y un archivo .g y otro archivo .g.hpp en la carpeta Archivos generados, que está en el disco pero no forma parte del proyecto. Modifica los archivos XAML para crear elementos de la interfaz de usuario y conéctalos a orígenes de datos (DataBinding). Modifica los archivos .h y .cpp files para agregar lógica personalizada para controladores de eventos. Los archivos generados automáticamente representan la transformación del marcado XAML en C ++ / CX. No modifiques estos archivos, pero puedes estudiarlos para comprender mejor cómo funciona el código que se esconde tras ellos. Básicamente, el archivo generado contiene una definición de clase parcial para un elemento raíz de XAML; esta clase es la misma clase que modificas en los archivos *.xaml.h y .cpp. Los archivos generados declaran los elementos secundarios de la interfaz de usuario de XAML como miembros de clase para que puedas hacer referencia a ellos en el código que escribas. Durante la compilación, el código generado y tu código se combinan en una definición de clase completa y, después, se compilan.
Veamos primero los archivos del proyecto.
- App.xaml, App.xaml.h, App.xaml.cpp: Representan el objeto Application, que es un punto de entrada de la aplicación. App.xaml no contiene marcado de interfaz de usuario de la página, pero puedes agregar estilos de interfaz de usuario y otros elementos a los que desees que se pueda acceder desde cualquier página. Los archivos de código subyacente contienen controladores para los eventos OnLaunched y OnSuspending. Por lo general, aquí tienes que agregar código personalizado para que inicialice tu aplicación cuando se inicie y realice la limpieza cuando se suspenda o finalice.
- MainPage.xaml, MainPage.xaml.h, MainPage.xaml.cpp: Contenga el marcado XAML y el código subyacente para la página de "inicio" predeterminada en una aplicación. No dispone de compatibilidad de navegación ni de controles integrados.
- pch.h, pch.cpp: Un archivo de encabezado precompilado y el archivo que lo incluye en su proyecto. En pch.h, puedes incluir cualquier encabezado que no cambie a menudo y que se incluyan en otros archivos de la solución.
- Package.appxmanifest: Un archivo XML que describe las funcionalidades del dispositivo que necesita su aplicación, así como la información de versión de su aplicación y otros metadatos. Para abrir este archivo en el Diseñador de manifiestos, solo tienes que hacer doble clic en él.
- HelloWorld_TemporaryKey.pfx: una clave que permite la implementación de la aplicación en este equipo desde Visual Studio.
Un primer vistazo al código
Si examinas el código de App.xaml.h, App.xaml.cpp en el proyecto compartido, verás que prácticamente todo es código C++ bastante familiar. Sin embargo, algunos elementos de sintaxis pueden no resultar tan familiares si estás comenzando con las aplicaciones de Windows en tiempo de ejecución o has trabajado con C++ o CLI. A continuación, te mostramos los elementos de sintaxis no estándares más comunes que verás en C++/CX:
Clases de referencia
Prácticamente todas las clases de Windows Runtime, en las que se incluyen todos los tipos de la API de Windows (XAML de Windows, las páginas de tu aplicación, la propia clase App, todos los objetos de red y dispositivo, todos los tipos de contenedor), se declaran como clase ref. (Algunos tipos de Windows son clase de valor o estructura de valor). Una clase de referencia se puede consumir desde cualquier lenguaje. En C ++/CX, la duración de estos tipos se rige por el recuento automático de referencias (no la recolección de basura) para que nunca elimine explícitamente estos objetos. También puedes crear tus propias clases de referencia.
namespace HelloWorld
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public ref class MainPage sealed
{
public:
MainPage();
};
}
Todos los tipos de Windows Runtime deben declararse en un espacio de nombres y, al contrario que en ISO C++, los propios tipos tienen un modificador de accesibilidad. El modificador public hace que los componentes de Windows Runtime puedan ver la clase fuera del espacio de nombres. La palabra clave sealed (sellada) significa que la clase no puede servir como una clase base. Prácticamente todas las clases de referencia están selladas; la herencia de clases no se usa mucho porque JavaScript no la comprende.
ref new y ^ (circunflejos)
Declaras una variable de una clase de referencia mediante el operador ^ (circunflejo) y creas una instancia del objeto con la nueva palabra clave de la referencia. Después accedes a los métodos de instancia del objeto mediante el operador ->, como un puntero de C++. Para acceder a los métodos estáticos, es necesario usar el operador ::, como en ISO C++.
En este código de abajo, usamos el nombre completo para crear una instancia del objeto y usamos el operador -> para llamar a un método de instancia.
Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapImage =
ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();
bitmapImage->SetSource(fileStream);
Por lo general, en un archivo .cpp file agregaríamos una directiva using namespace Windows::UI::Xaml::Media::Imaging
y la palabra clave auto, para que el mismo código tuviese este aspecto:
auto bitmapImage = ref new BitmapImage();
bitmapImage->SetSource(fileStream);
Propiedades
Una clase de referencia puede tener propiedades que, al igual que en los lenguajes administrados, son funciones de miembros especiales que aparecen como campos del código que se consume.
public ref class SaveStateEventArgs sealed
{
public:
// Declare the property
property Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ PageState
{
Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ get();
}
...
};
...
// consume the property like a public field
void PhotoPage::SaveState(Object^ sender, Common::SaveStateEventArgs^ e)
{
if (mruToken != nullptr && !mruToken->IsEmpty())
{
e->PageState->Insert("mruToken", mruToken);
}
}
Delegados
Al igual que en los lenguajes administrados, un delegado es un tipo de referencia que encapsula una función con una firma específica. Se usan principalmente con eventos y controladores de eventos
// Delegate declaration (within namespace scope)
public delegate void LoadStateEventHandler(Platform::Object^ sender, LoadStateEventArgs^ e);
// Event declaration (class scope)
public ref class NavigationHelper sealed
{
public:
event LoadStateEventHandler^ LoadState;
};
// Create the event handler in consuming class
MainPage::MainPage()
{
auto navigationHelper = ref new Common::NavigationHelper(this);
navigationHelper->LoadState += ref new Common::LoadStateEventHandler(this, &MainPage::LoadState);
}
Agregar contenido a la aplicación
Vamos a agregar algo de contenido a la aplicación.
Paso 1: Modificar su página de inicio
En el Explorador de soluciones, abre MainPage.xaml.
Crea controles para la interfaz de usuario agregando el siguiente código XAML a la raíz Grid, justo antes de su etiqueta de cierre. Contiene StackPanel con TextBlock que pregunta el nombre del usuario, un elemento TextBox que acepta el nombre del usuario, un elemento Button y otro elemento TextBlock.
<StackPanel x:Name="contentPanel" Margin="120,30,0,0"> <TextBlock HorizontalAlignment="Left" Text="Hello World" FontSize="36"/> <TextBlock Text="What's your name?"/> <StackPanel x:Name="inputPanel" Orientation="Horizontal" Margin="0,20,0,20"> <TextBox x:Name="nameInput" Width="300" HorizontalAlignment="Left"/> <Button x:Name="inputButton" Content="Say "Hello""/> </StackPanel> <TextBlock x:Name="greetingOutput"/> </StackPanel>
En este punto, has creado una aplicación universal de Windows muy básica. Para ver la apariencia de la aplicación para UWP, presiona F5 para compilar, implementar y ejecutar la aplicación en modo de depuración.
Primero aparece la pantalla de presentación predeterminada. Muestra una imagen (Assets\SplashScreen.scale-100.png) y un color de fondo que se especifican en el archivo de manifiesto de la aplicación. Para aprender a personalizar la pantalla de presentación, consulta Agregar una pantalla de presentación.
Cuando desaparezca la pantalla de presentación, aparecerá tu aplicación. Muestra la página principal de la aplicación.
Aunque todavía no hace muchas cosas, te felicitamos por haber compilado tu primera aplicación para la Plataforma universal de Windows.
Para detener la depuración y cerrar la aplicación, vuelve a Visual Studio y presiona Mayús+F5.
Si quieres más información, consulta el tema sobre cómo ejecutar una aplicación de la Tienda en Visual Studio.
En la aplicación puedes escribir en el TextBox, pero si haces clic en el Button, no se realiza ninguna acción. En los pasos posteriores, crearás un controlador de eventos para el evento Click del botón que muestra un saludo personalizado.
Paso 2: Crear un controlador de eventos
En MainPage.xaml, en la vista de diseño o XAML, selecciona el Button "Saluda" del StackPanel que agregaste anteriormente.
Abra la Ventana de propiedades presionando F4 y después elija el botón Eventos ().
Encuentra el evento Click. En su cuadro de texto, escribe el nombre de la función que controla el evento Click. Para este ejemplo, escriba "Button_Click".
Presiona Entrar. El método de controlador de eventos se crea en MainPage.xaml.cpp y se abre de forma que puedas agregar el código que se ejecutará cuando se produzca el evento.
Al mismo tiempo, en MainPage.xaml, el XAML para Button se actualiza para declarar el controlador de eventos de Click, de esta manera:
<Button Content="Say "Hello"" Click="Button_Click"/>
Podrías haber agregado esto simplemente al código xaml de forma manual, lo cual puede resultar útil si no se carga el diseñador. Si escribes esto manualmente, escribe "Click" y deja que IntelliSense haga aparecer la opción para agregar un nuevo controlador de eventos. De este modo, Visual Studio creará la declaración del método y el código auxiliar necesarios.
El diseñador no se puede cargar si se produce una excepción no controlada durante la representación. La representación en el diseñador implica ejecutar una versión en tiempo de diseño de la página. Puede ser útil deshabilitar la ejecución de código de usuario. Puedes hacerlo cambiando la configuración en el cuadro de diálogo Herramientas, Opciones. En Diseñador XAML, desactiva la casilla Ejecutar código del proyecto en el diseñador XAML (si se admite) .
- En MainPage.xaml.cpp, agregue el siguiente código al controlador de eventos Button_Click que acaba de crear. Este código recupera el nombre de usuario del control de la clase TextBox
nameInput
y lo usa para crear un saludo. La clase TextBlockgreetingOutput
muestra el resultado.
void HelloWorld::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
greetingOutput->Text = "Hello, " + nameInput->Text + "!";
}
- Establece el proyecto como el proyecto de inicio y presiona F5 para compilar y ejecutar la aplicación. Cuando escribes un nombre en el cuadro de texto y haces clic en el botón, la aplicación muestra un saludo personalizado.
Paso 3: Estilo de la página de inicio
Elección de un tema
Es fácil personalizar la apariencia de tu aplicación. De manera predeterminada, tu aplicación usa recursos con un estilo claro. Los recursos del sistema también incluyen un tema claro. Vamos a probarlo y ver cómo es.
Para cambiar al tema oscuro
Abre App.xaml.
En la etiqueta de apertura Aplicación, edita la propiedad RequestedTheme y establece su valor en Oscuro:
RequestedTheme="Dark"
Esta es la etiqueta Aplicación completa con el tema oscuro:
<Application x:Class="HelloWorld.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:HelloWorld" RequestedTheme="Dark">
Presiona F5 para compilarla y ejecutarla. Observa que usa el tema oscuro.
¿Qué tema deberías usar? El que más te guste. Esta es nuestra perspectiva: te recomendamos que uses el tema oscuro para las aplicaciones que muestren principalmente imágenes o vídeo y el tema claro para las aplicaciones que contengan mucho texto. Si vas a usar un esquema de colores personalizado, usa el tema que mejor se ajuste a la apariencia de la aplicación. En el resto de este tutorial, usaremos el tema claro en las capturas de pantalla.
Nota: El tema se aplica cuando se inicia la aplicación y no se puede cambiar mientras la aplicación se está ejecutando.
Usar estilos del sistema
Ahora mismo, en la aplicación de Windows el texto es muy pequeño y difícil de leer. Vamos a solucionarlo aplicando un estilo del sistema.
Para cambiar el estilo de un elemento
En el proyecto de Windows, abre MainPage.xaml.
En la vista de diseño o en XAML, selecciona el TextBlock "¿Cómo te llamas?" que agregaste anteriormente.
En la ventana Propiedades (F4), elija el botón Propiedades () en la parte superior derecha.
Expande el grupo Texto y establece el tamaño de fuente en 18 px.
Expande el grupo Varios y busca la propiedad Style.
Haz clic en el marcador de propiedad (el cuadro verde situado a la derecha de la propiedad Style) y después, en el menú, elige Recurso del sistema>BaseTextBlockStyle.
BaseTextBlockStyle es un recurso que se define en el objeto ResourceDictionary en <raíz>\Archivos de programa\Windows Kits\10\Include\winrt\xaml\design\generic.xaml.
En la superficie de diseño XAML, la apariencia del texto cambia. En el editor XAML, se actualiza el XAML para TextBlock:
<TextBlock Text="What's your name?" Style="{ThemeResource BaseTextBlockStyle}"/>
Repite el proceso para establecer el tamaño de fuente y asignar BaseTextBlockStyle al elemento
greetingOutput
TextBlock.Sugerencia: Aunque no haya texto en este TextBlock, cuando mueve el puntero sobre la superficie de diseño XAML, un contorno azul muestra dónde está para que pueda seleccionarlo.
Tu XAML ahora tiene esta apariencia:
<StackPanel x:Name="contentPanel" Margin="120,30,0,0">
<TextBlock Style="{ThemeResource BaseTextBlockStyle}" FontSize="18" Text="What's your name?"/>
<StackPanel x:Name="inputPanel" Orientation="Horizontal" Margin="0,20,0,20">
<TextBox x:Name="nameInput" Width="300" HorizontalAlignment="Left"/>
<Button x:Name="inputButton" Content="Say "Hello"" Click="Button_Click"/>
</StackPanel>
<TextBlock Style="{ThemeResource BaseTextBlockStyle}" FontSize="18" x:Name="greetingOutput"/>
</StackPanel>
- Presiona F5 para compilar y ejecutar la aplicación. Ahora tiene esta apariencia:
Paso 4: Adaptar la interfaz de usuario a diferentes tamaños de ventana
Ahora haremos que la interfaz de usuario se adapte a diferentes tamaños de pantalla para que se vea correctamente en los dispositivos móviles. Para ello, agrega VisualStateManager y establece las propiedades que se aplican a diferentes estados visuales.
Para ajustar el diseño de interfaz de usuario
- En el editor XAML, agrega este bloque de XAML después de la etiqueta de apertura del elemento raíz Grid.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="wideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="641" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="narrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="contentPanel.Margin" Value="20,30,0,0"/>
<Setter Target="inputPanel.Orientation" Value="Vertical"/>
<Setter Target="inputButton.Margin" Value="0,4,0,0"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
- Depura la aplicación en el equipo local. Verás que la interfaz de usuario es igual que antes, a menos que la ventana tenga un ancho inferior a 641 píxeles independientes del dispositivo (DIP).
- Depura la aplicación en el emulador de dispositivos móviles. Observa que la interfaz de usuario use las propiedades definidas en
narrowState
y aparezca correctamente en la pantalla pequeña.
Si has usado VisualStateManager en versiones anteriores de XAML, puedes observar que aquí el XAML usa una sintaxis simplificada.
El VisualState llamado wideState
tiene un AdaptiveTrigger con su propiedad MinWindowWidth establecida en 641. Esto significa que el estado se aplicará únicamente cuando el ancho de la ventana no sea inferior al mínimo de 641 DIP. Para este estado no definas ningún objeto Setter a fin de que se usen las propiedades de diseño definidas en el XAML para el contenido de la página.
El segundo VisualState, narrowState
, tiene un AdaptiveTrigger con su propiedad MinWindowWidth establecida en 0. Este estado se aplica cuando el ancho de la ventana es mayor que 0, pero inferior a 641 DIP. (En 641 DIP, se aplica el wideState
.) En este estado, sí define algunos objetos Setter para cambiar las propiedades de diseño de los controles en la interfaz de usuario:
- Reduce el margen izquierdo del elemento
contentPanel
de 120 a 20. - Cambias Orientation del elemento
inputPanel
desde Horizontal a Vertical. - Agregas un margen superior de 4 DIP al elemento
inputButton
.
Resumen
Felicidades, has completado el primer tutorial. En él aprendiste cómo se agrega contenido a una aplicación universal de Windows, cómo se le agrega interactividad y cómo se cambia su apariencia.
Pasos siguientes
Si tiene un proyecto de aplicación universal de Windows destinado a Windows 8.1 o Windows Phone 8.1, puede portarlo a Windows 10 o Windows 11. No hay ningún proceso automático para ello, pero puede hacerlo manualmente. Empieza con un nuevo proyecto de Windows Universal para obtener la estructura del sistema de proyecto más reciente y los archivos de manifiesto, copia los archivos de código en la estructura de directorios del proyecto, agrega los elementos al proyecto y reescribe el XAML con VisualStateManager, como se indica en este tema. Para obtener más información, consulta Migración de un proyecto de Windows Runtime 8 a un proyecto de la Plataforma universal de Windows (UWP) y Migrar a la Plataforma universal de Windows (C++).
Si tienes código C++ que desees integrar en una aplicación para UWP, por ejemplo, para crear una nueva interfaz de usuario de UWP para una aplicación existente, consulta Cómo: Usar existente C++ código en un proyecto de Windows Universal.