Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
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, puede verse 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 descargar, consulta Consigue 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 entre aplicaciones de escritorio C++ y aplicaciones UWP
Si viene de una experiencia en la programación de escritorio de Windows en C++, probablemente encontrará que algunos aspectos de la escritura de aplicaciones para UWP le resulten familiares, pero otros aspectos requieren cierto aprendizaje.
¿Qué es lo mismo?
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 del sistema operativo 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 Runtime, aunque Win32 sigue estando disponible en los dispositivos de Windows para realizar algunas funciones.
Usas C++/CX para consumir y crear objetos de Windows Runtime. C++/CX permite controlar excepciones de C++, admite delegados y eventos, y permite el recuento automático 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 para el código de tu 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 la Microsoft Store la aplicación se verifica como segura mediante un proceso de certificación y se hace visible a millones de clientes potenciales.
La aplicación de la Tienda Hola mundo en C++/CX
Nuestra primera aplicación es un «Hola mundo» 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. La plataforma universal de Windows (UWP) te permite usar un único proyecto para el código de la aplicación y XAML y ejecutar la aplicación en equipos de escritorio, portátiles y tabletas con Windows.
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 esta opción, asegúrate de tener instaladas las herramientas de desarrollo de las aplicaciones universales de Windows. Consulta Primeros pasos 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 Activar tu dispositivo para 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. En tiempo de 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 code-behind 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: Contienen 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 incluya 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 Manifest Designer, 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 Runtime o has trabajado con C++/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 (controles XAML, 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 ref class se puede consumir desde cualquier lenguaje. En C++/CX, el tiempo de vida de estos tipos se rige por el recuento de referencias automático (no la recolección de basura), de modo que nunca tenga que eliminar 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 la clase sea visible para los componentes de Windows Runtime 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 ref están selladas; la herencia de clases no se usa mucho porque JavaScript no la comprende.
ref new y ^ (circunflejos)
Se declara una variable de una clase de referencia mediante el operador ^ (circunflejo) y se crea una instancia del objeto con la palabra clave ref new. Después de eso 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 el código siguiente, usamos el nombre completamente calificado para crear una instancia de un 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 para el código cliente.
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 creado tu primera aplicación para 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 Store 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 "Say Hello" 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 maneja el evento Click. Para este ejemplo, escriba "Button_Click".
Presiona Intro. 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 añadir un nuevo controlador de eventos. De este modo, Visual Studio creará la declaración del método y el stub 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 del usuario del control
nameInputTextBox y lo usa para crear un saludo. ElgreetingOutputTextBlock 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: Personaliza 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 Application, edita la propiedad RequestedTheme y establece su valor en Dark:
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.
Uso de 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.Amplía el grupo Texto y establece el tamaño de fuente en 18 px.
Expanda el grupo Varios y busca la propiedad Estilo.
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 ResourceDictionary en <root>\Program Files\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
greetingOutputTextBlock.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 un 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 de la etiqueta 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. Observa 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 usa las propiedades definidas en
narrowStatey aparece 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 debe aplicarse únicamente cuando el ancho de la ventana no sea inferior al mínimo de 641 DIP. Para este estado no defines ningún objeto Setter, por lo que se usan 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
contentPanelde 120 a 20. - Cambias la Orientation del elemento
inputPaneldesde Horizontal a Vertical. - Agregas un margen superior de 4 DIP al elemento
inputButton.
Resumen
Felicidades, has completado el primer tutorial. En él se enseñaba 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.
Siguientes pasos
Para migrar un proyecto de aplicación de Windows Runtime anterior a Windows 10 o Windows 11, comience con un nuevo proyecto de Windows Universal para obtener la estructura y los archivos de manifiesto del sistema de proyecto más recientes, copie los archivos de código en la estructura de directorios del proyecto, agregue los elementos al proyecto y vuelva a escribir el XAML con VisualStateManager según las instrucciones de 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 código C++ existente en un proyecto de Windows Universal.