Compartir a través de


Compilación de una aplicación Win2D sencilla

En este tutorial se presentan algunas de las funcionalidades básicas de dibujo de Win2D. Aprenderá a:

  • Agregue Win2D a un proyecto de Windows XAML de C#.
  • Dibujar texto y geometría.
  • Aplicar efectos de filtro.
  • Animar el contenido de Win2D.
  • Seguir los procedimientos recomendados de Win2D.

Configuración del equipo de desarrollo

Asegúrese de configurar la máquina con todas las herramientas necesarias:

Creación de un nuevo proyecto de Win2D

Siga los pasos del inicio rápido "Hello, World!" de Win2D para crear un nuevo proyecto mediante Win2D y agregar una referencia al paquete NuGet Win2D. Puedes usar WinUI 3 (Windows App SDK) o la Plataforma universal de Windows (UWP).

Agregar un CanvasControl de Win2D al XAML de la aplicación

  1. Para poder usar Win2D, necesita algún lugar para dibujar los gráficos. En una aplicación XAML, la manera más sencilla de hacerlo es agregar CanvasControl a la página XAML.

Antes de continuar, asegúrese primero de que la opción Arquitectura del proyecto esté establecida en x86 o x64 y no en Any CPU. Win2D se implementa en C++ y, por lo tanto, los proyectos que usan Win2D deben tener como destino una arquitectura de CPU específica.

  1. Vaya a MainPage.xaml en el proyecto haciendo doble clic en él en el Explorador de soluciones. Se abrirá el archivo. Para mayor comodidad, puede hacer doble clic en el botón XAML de la pestaña Diseñador; esto ocultará el diseñador visual y reservará todo el espacio para la vista de código.

  2. Antes de agregar el control, primero tienes que indicar a XAML dónde se define CanvasControl. Para ello, vaya a la definición del elemento Page y agregue esta directiva: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". El XAML debe tener ahora un aspecto similar al siguiente:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">
  1. Ahora, agregue un nuevo canvas:CanvasControl como elemento secundario al elemento raíz Grid. Asigne un nombre al control, por ejemplo, "canvas". El XAML debe tener ahora un aspecto similar al siguiente:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. A continuación, defina un controlador de eventos para el evento Draw. CanvasControl genera Draw cada vez que la aplicación necesite dibujar o volver a dibujar su contenido. La manera más fácil es permitir que Autocompletar de Visual Studio le ayude. En la definición de CanvasControl, comience a escribir un nuevo atributo para el controlador de eventos Draw:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Nota:

Una vez que haya escrito en Draw=", Visual Studio debe mostrar un cuadro que le pida que rellene automáticamente la definición correcta para el controlador de eventos. Presione TAB para aceptar el controlador de eventos predeterminado de Visual Studio. Esto también agregará automáticamente un método de controlador de eventos con formato correcto en el código subyacente (`MainPage.xaml.cs``). No se preocupe si no usó Autocompletar; puede agregar manualmente el método del controlador de eventos en el paso siguiente.

Dibujar el primer texto en Win2D

  1. Ahora, vamos al código de C# subyacente. Abra MainPage.xaml.cs desde el Explorador de soluciones.

  2. En la parte superior del archivo de C# hay varias definiciones de espacio de nombres. Agregue los siguientes espacios de nombres:

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. A continuación, debería ver el siguiente controlador de eventos en blanco que insertó en Autocompletar:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(Si no usó Autocompletar en el paso anterior, agregue este código ahora).

  1. El parámetro CanvasDrawEventArgs expone un miembro, DrawingSession, que es del tipo CanvasDrawingSession. Esta clase proporciona la mayor parte de la funcionalidad básica de dibujo en Win2D: tiene métodos como CanvasDrawingSession.DrawRectangle,CanvasDrawingSession.DrawImage y el método que necesita para dibujar texto,CanvasDrawingSession.DrawText.

Agregue el código siguiente al método canvas_Draw:

args.DrawingSession.DrawText("Hello, World!", 100, 100, Colors.Black);

El primer argumento, "Hello, World!", es la cadena que quiere que Win2D muestre. Los dos "100" indican a Win2D que desfase este texto en 100 DIPs (píxeles independientes del dispositivo) hacia la derecha y hacia abajo. Por último, Colors.Black define el color del texto.

  1. Ahora ya está listo para ejecutar la primera aplicación Win2D. Presione la tecla F5 para compilar e iniciar. Deberá ver una ventana vacía con "Hola mundo" en negro.

Eliminación correcta de recursos de Win2D

  1. Antes de continuar dibujando otros tipos de contenido, primero debe agregar código para asegurarse de que la aplicación evita pérdidas de memoria. La mayoría de las aplicaciones Win2D escritas en un lenguaje .NET y el uso de un control Win2D como CanvasControl deben seguir los pasos siguientes. Estrictamente hablando, la sencilla aplicación "Hola mundo" no se ve afectada, pero esta es una buena práctica para seguir en general.

Para obtener más información, consulte Evitar pérdidas de memoria.

  1. Abra MainPage.xaml y busque el elemento Page XAML que contiene CanvasControl. Debe ser el primer elemento del archivo.

  2. Agregue un controlador para el evento Unloaded. El XAML debe tener este aspecto:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d"
    Unloaded="Page_Unloaded">
  1. Vaya a MainPage.xaml.cs y busque el controlador de eventos Page_Unloaded. Agregue el código siguiente:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. Si la aplicación contiene varios controles Win2D, debes repetir los pasos anteriores para cada página XAML que contenga un control Win2D. Actualmente, su aplicación tiene un solo CanvasControl así que ya ha terminado.

Dibujar algunas formas

  1. Es tan fácil agregar geometría 2D a la aplicación. Agregue el código siguiente al final de canvas_Draw:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

Los argumentos de estos dos métodos son similares a DrawText. Un círculo se define mediante un punto central (125, 125), un radio (100) y un color (verde). Una línea se define por un principio (0, 0), un final (50, 200) y un color (rojo).

  1. Ahora, presione F5 para ejecutar la aplicación. Debería ver "Hola mundo" junto con un círculo verde y una línea roja.

Es posible que se pregunte cómo controlar opciones de dibujo más avanzadas, como grosor de línea y guiones, o opciones de relleno más complejas, como el uso de pinceles. Win2D proporciona todas estas opciones y mucho más, y facilita su uso cuando quieras. Todos los métodos Draw(...) ofrecen muchas sobrecargas que pueden aceptar parámetros adicionales, como CanvasTextFormat (familia de fuentes, tamaño, etc.) y CanvasStrokeStyle (guiones, puntos, finales, etc.). No dude en explorar la superficie de API para obtener más información sobre estas opciones.

Generación dinámica de parámetros de dibujo

  1. Ahora, vamos a agregar cierta variedad dibujando un montón de formas y texto con colores aleatorios.

Agregue el código siguiente a la parte superior de la clase MainPage. Esta es la funcionalidad auxiliar para generar valores aleatorios que usará al dibujar:

Random rnd = new Random();
private Vector2 RndPosition()
{
    double x = rnd.NextDouble() * 500f;
    double y = rnd.NextDouble() * 500f;
    return new Vector2((float)x, (float)y);
}

private float RndRadius()
{
    return (float)rnd.NextDouble() * 150f;
}

private byte RndByte()
{
    return (byte)rnd.Next(256);
}
  1. Modifique el método canvas_Draw para dibujar mediante estos parámetros aleatorios:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}

Vamos a desglosar cómo DrawText ha cambiado. "Hello, World!" sigue siendo el mismo que antes. Los parámetros de desplazamiento x e y se han reemplazado por un único System.Numerics.Vector2 generado por RndPosition. Por último, en lugar de usar un color predefinido, Color.FromArgb permite definir un color mediante los valores A, R, G y B. A es alfa o el nivel de opacidad; en este caso siempre querrá que sea completamente opaco (255).

DrawCircle y DrawLine funcionan de forma similar a DrawText.

  1. Por último, ajuste el código de dibujo en un bucle for. Debería terminar con el código de canvas_Draw siguiente:
for (int i = 0; i < 100; i++)
{
    args.DrawingSession.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    args.DrawingSession.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
}
  1. Ejecute la aplicación de nuevo. Debería ver un montón de texto, líneas y círculos con posiciones y tamaños aleatorios.

Aplicar un efecto de imagen al contenido

Los efectos de imagen, también conocidos como efectos de filtro, son transformaciones gráficas que se aplican a los datos de píxeles. La saturación, la rotación de matiz y el desenfoque gaussiano son algunos efectos de imagen comunes. Los efectos de imagen se pueden encadenar, lo que produce una apariencia visual sofisticada para un esfuerzo mínimo.

Para usar efectos de imagen, proporcione una imagen de origen (el contenido con el que empieza), creando un efecto como GaussianBlurEffect, estableciendo propiedades como BlurAmount y, a continuación, dibujando la salida del efecto con DrawImage.

Para aplicar un efecto de imagen al texto y las formas, primero debe representar ese contenido en CanvasCommandList. Este objeto se puede usar como entrada para el efecto.

  1. Cambie el método canvas_Draw para usar el código siguiente:
CanvasCommandList cl = new CanvasCommandList(sender);

using (CanvasDrawingSession clds = cl.CreateDrawingSession())
{
    for (int i = 0; i < 100; i++)
    {
        clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
    }
}

Al igual que cómo se obtiene un CanvasDrawingSession de CanvasDrawEventArgs con el que se puede dibujar, puede crear un CanvasDrawingSession a partir de un CanvasCommandList. La única diferencia es que cuando se dibuja en la sesión de dibujo de la lista de comandos (clds), no se representa directamente en CanvasControl. En su lugar, la lista de comandos es un objeto intermedio que almacena los resultados de la representación para su uso posterior.

Es posible que haya observado el bloque using que encapsula la sesión de dibujo de la lista de comandos. Las sesiones de dibujo implementan IDisposable y deben eliminarse cuando haya terminado de representarse (el bloque using se encarga). El CanvasDrawingSession que obtiene de CanvasDrawEventArgs se cierra automáticamente, pero debe eliminar las sesiones de dibujo que haya creado explícitamente.

  1. Por último, defina GaussianBlurEffect agregando el código siguiente al final del método canvas_Draw:
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. Ejecute la aplicación de nuevo. Debería ver las líneas, el texto y los círculos con una apariencia borrosa.

Animar la aplicación con CanvasAnimatedControl

. Win2D ofrece la posibilidad de actualizar y animar el contenido en tiempo real, por ejemplo cambiando el radio de desenfoque del desenfoque gaussiano con cada fotograma. Para ello, usará CanvasAnimatedControl.

CanvasControl es más adecuado para la mayoría de contenido de gráficos estáticos: solo genera el evento Draw cuando el contenido debe actualizarse o volver a dibujarse. Si ha cambiado continuamente el contenido, debe considerar la posibilidad de usar CanvasAnimatedControl en su lugar. Los dos controles funcionan de forma muy similar, excepto CanvasAnimatedControl que genera el evento Draw de forma periódica; de manera predeterminada se llama 60 veces por segundo.

  1. Para cambiar a CanvasAnimatedControl, vaya a MainPage.xaml, elimine la línea CanvasControl y reemplácela por el código XAML siguiente:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

Al igual que con CanvasControl, deje que AutoComplete cree el controlador de eventos Draw automáticamente. De manera predeterminada, Visual Studio denominará a este controlador canvas_Draw_1 porque ya canvas_Draw existe; aquí, hemos cambiado el nombre del método canvas_AnimatedDraw para aclarar que se trata de un evento diferente.

Además, también está controlando un evento nuevo, CreateResources. Una vez más, deje que Autocompletar cree el controlador.

Ahora que la aplicación se volverá a dibujar en 60 fotogramas por segundo, es más eficaz crear los recursos visuales Win2D una vez y reutilizarlos con cada fotograma. Es ineficaz crear un CanvasCommandList y dibujar 300 elementos en él 60 veces por segundo cuando el contenido permanece estático. CreateResources es un evento que se desencadena solo cuando Win2D determina que necesita volver a crear los recursos visuales, como cuando se carga la página.

  1. Vuelva a MainPage.xaml.cs. Busque el método canvas_Draw que deberá tener este aspecto:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
    CanvasCommandList cl = new CanvasCommandList(sender);
    using (CanvasDrawingSession clds = cl.CreateDrawingSession())
    {
        for (int i = 0; i < 100; i++)
        {
            clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        }
    }

    GaussianBlurEffect blur = new GaussianBlurEffect();
    blur.Source = cl;
    blur.BlurAmount = 10.0f;
    args.DrawingSession.DrawImage(blur);
}

La gran mayoría de este código de dibujo existente no necesita ejecutarse con cada fotograma: la lista de comandos que contiene el texto, las líneas y los círculos permanecen iguales con cada fotograma y lo único que cambia es el radio de desenfoque. Por lo tanto, puede mover este código "estático" a CreateResources.

Para ello, corte primero (CTRL+X) todo el contenido de canvas_Draw, excepto la última línea (args.DrawingSession.DrawImage(blur);). Ahora puede eliminar el resto de canvas_Draw puesto que ya no es necesario: recuerde que CanvasAnimatedControl tiene su propio evento Draw distinto.

  1. Busque el método canvas_CreateResources generado automáticamente:
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, 
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}

Pegue (CTRL+V) el código cortado previamente en este método. A continuación, mueva la declaración de GaussianBlurEffect fuera del cuerpo del método para que la variable se convierta en miembro de la clase MainPage. El código debe tener un aspecto parecido al siguiente.

GaussianBlurEffect blur;
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender,
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{
    CanvasCommandList cl = new CanvasCommandList(sender);
    using (CanvasDrawingSession clds = cl.CreateDrawingSession())
    {
        for (int i = 0; i < 100; i++)
        {
            clds.DrawText("Hello, World!", RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawCircle(RndPosition(), RndRadius(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
            clds.DrawLine(RndPosition(), RndPosition(), Color.FromArgb(255, RndByte(), RndByte(), RndByte()));
        }
    }

    blur = new GaussianBlurEffect()
    {
        Source = cl,
        BlurAmount = 10.0f
    };
}
  1. Ahora puede animar el desenfoque gaussiano. Busque el método canvas_DrawAnimated y agregue el código siguiente:
private void canvas_DrawAnimated(
    Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
{
    float radius = (float)(1 + Math.Sin(args.Timing.TotalTime.TotalSeconds)) * 10f;
    blur.BlurAmount = radius;
    args.DrawingSession.DrawImage(blur);
}

Esto lee el tiempo total transcurrido proporcionado por CanvasAnimatedDrawEventArgs y lo usa para calcular la cantidad de desenfoque deseada; la función sine proporciona una variación interesante a lo largo del tiempo. Por último, se representa el GaussianBlurEffect.

  1. Ejecute la aplicación para ver el cambio de contenido borroso a lo largo del tiempo.

Enhorabuena por completar este tutorial de inicio rápido. Esperamos que haya visto cómo puede usar Win2D para crear una escena visual enriquecida y animada con unas pocas líneas de código XAML y C#.