Compartilhar via


Criar um aplicativo Win2D simples

Este tutorial apresenta alguns dos recursos básicos de desenho do Win2D. Você aprenderá a:

  • Adicione o Win2D a um projeto do Windows em XAML e C#.
  • Desenhe texto e geometria.
  • Aplique efeitos de filtro.
  • Anime conteúdo do Win2D.
  • Siga as práticas recomendadas do Win2D.

Configurar seu computador de desenvolvimento

Você deve configurar seu computador com todas as ferramentas necessárias:

Criar um novo projeto do Win2D

Siga as etapas no início rápido "Olá, mundo!" do Win2D para criar um novo projeto usando o Win2D e adicionar uma referência ao pacote NuGet do Win2D. Você pode usar a WinUI 3 (SDK do Aplicativo do Windows) ou a UWP (Plataforma Universal do Windows).

Adicionar um Win2D CanvasControl ao XAML do aplicativo

  1. Para usar o Win2D, você precisa de algum lugar para desenhar seus gráficos. Em um aplicativo XAML, a maneira mais simples de fazer isso é adicionar um CanvasControl à página do XAML.

Antes de continuar, primeiro verifique se a opção Arquitetura do projeto está definida como x86 ou x64 e não como Any CPU. O Win2D é implementado em C++, portanto, os projetos que usam o Win2D precisam ser direcionados a uma arquitetura de CPU específica.

  1. Navegue até MainPage.xaml no seu projeto clicando duas vezes nele no Gerenciador de Soluções. Isso abrirá o arquivo. Para sua conveniência, você pode clicar duas vezes no botão XAML da guia Designer, isso ocultará o visual designer e reservará todo o espaço para o modo de exibição de código.

  2. Antes de adicionar o controle, primeiro informe ao XAML onde o CanvasControl está definido. Para fazer isso, vá para a definição do elemento da Página e adicione esta diretiva: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". Agora, seu XAML deve ter esta aparência:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">
  1. Agora, adicione um novo canvas:CanvasControl como elemento filho ao elemento raiz Grade. Dê um nome ao controle, por exemplo, "tela". Agora, seu XAML deve ter esta aparência:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. Em seguida, defina um manipulador de eventos para o evento Desenhar. O CanvasControl gera Draw sempre que seu aplicativo precisa desenhar ou redesenhar seu conteúdo. A forma mais fácil é permitindo que o Preenchimento Automático do Visual Studio ajude você. Na definição de CanvasControl, comece a digitar um novo atributo para o manipulador de eventos Draw:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Observação

Depois de entrar em Draw=", o Visual Studio deverá abrir uma caixa solicitando que você a permita p preenchimento automático da definição certa para o manipulador de eventos. Pressione TAB para aceitar o manipulador de eventos padrão do Visual Studio. Isso também adicionará automaticamente um método de manipulador de eventos formatado corretamente em seu code-behind ("MainPage.xaml.cs"). Não se preocupe caso não tenha usado o Preenchimento Automático; você poderá adicionar manualmente o método do manipulador de eventos na próxima etapa.

Desenhar seu primeiro texto no Win2D

  1. Agora, vamos para o code-behind C#. Abra MainPage.xaml.cs no Gerenciador de Soluções.

  2. Na parte superior do arquivo C#, há várias definições de namespace. Adicione os seguintes namespaces:

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. Em seguida, você deverá ver o seguinte manipulador de eventos em branco que foi inserido pelo Preenchimento Automático:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(Caso não tenha usado o Preenchimento Automático na etapa anterior, adicione este código agora.)

  1. O parâmetro CanvasDrawEventArgs expõe um membro, DrawingSession, que é do tipo CanvasDrawingSession. Essa classe fornece a maior parte da funcionalidade básica de desenho no Win2D: ela tem métodos como CanvasDrawingSession.DrawRectangle,CanvasDrawingSession.DrawImage e o método necessário para desenhar texto, CanvasDrawingSession.DrawText.

Adicione o seguinte código ao método canvas_Draw:

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

O primeiro argumento, "Hello, World!", é a cadeia de caracteres que você deseja que o Win2D exiba. Os dois "100" indicam ao Win2D para compensar esse texto por 100 DIPs (pixels independentes de dispositivo) para a direita e para baixo. Por fim, Colors.Black define a cor do texto.

  1. Agora você está pronto para executar seu primeiro aplicativo Win2D. Pressione a tecla F5 para compilar e iniciar. Você deve ver uma janela vazia com "Olá, mundo!" em preto.

Descartar corretamente os recursos do Win2D

  1. Antes de continuar a desenhar outros tipos de conteúdo, você deve adicionar um código para garantir que seu aplicativo evite perdas de memória. A maioria dos aplicativos Win2D escritos em uma linguagem .NET e usando um controle do Win2D como o CanvasControl precisa seguir as etapas abaixo. Estritamente falando, seu aplicativo "Olá, mundo" simples não é afetado, mas essa é uma boa prática a seguir em geral.

Para obter mais informações, consulte Como evitar perdas de memória.

  1. Abra MainPage.xaml e localize o elemento XAML da Página que contém o CanvasControl. Ele deve ser o primeiro elemento do arquivo.

  2. Adicione um manipulador para o evento Unloaded. A exibição XAML deve se parecer com o seguinte:

<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. Vá para MainPage.xaml.cs e localize o manipulador de eventos Page_Unloaded. Adicione o seguinte código:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. Se o aplicativo contiver vários controles do Win2D, você precisará repetir as etapas acima para cada página XAML que contiver um controle do Win2D. No momento, seu aplicativo tem apenas um CanvasControl, portanto, você está pronto.

Desenhar algumas formas

  1. É muito fácil adicionar geometria 2D ao seu aplicativo. Adicione o seguinte código ao final de canvas_Draw:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

Os argumentos para esses dois métodos são semelhantes a DrawText. Um círculo é definido por um ponto central (125, 125), um raio (100) e uma cor (verde). Uma linha é definida por um início (0, 0), um final (50, 200) e uma cor (vermelho).

  1. Agora pressione F5 para executar o aplicativo. Você deve ver o "Olá, mundo!" junto com um círculo verde e uma linha vermelha.

Você deve estar se perguntando como controlar opções de desenho mais avançadas, como espessura e traços de linha, ou opções de preenchimento mais complexas, como o uso de pincéis. O Win2D fornece todas essas opções e muito mais, além de facilitar o uso delas quando você quiser. Todos os métodos Draw(...) oferecem muitas sobrecargas que podem aceitar parâmetros adicionais, como CanvasTextFormat (família de fontes, tamanho etc.) e CanvasStrokeStyle (traços, pontos, limites finais etc). Fique à vontade para explorar a superfície da API para saber mais sobre essas opções.

Gerar parâmetros de desenho dinamicamente

  1. Agora, vamos incluir algumas variedades desenhando um monte de formas e texto com cores aleatórias.

Adicione o código a seguir à parte superior da sua classe MainPage. Essa é a funcionalidade auxiliar para gerar valores aleatórios que você usará ao desenhar:

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 seu método canvas_Draw para desenhar usando estes parâmetros aleatórios:
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 analisar como DrawText mudou. "Hello, World!" permanece o mesmo de antes. Os parâmetros de deslocamento x e y foram substituídos por um único System.Numerics.Vector2 que é gerado por RndPosition. Por fim, em vez de usar uma cor predefinida, Color.FromArgb permite que você defina uma cor usando os valores A, R, G e B. A é alfa, ou o nível de opacidade; nesse caso, o desejado é sempre ser totalmente opaco (255).

DrawCircle e DrawLine operam de modo semelhante a DrawText.

  1. Por fim, encapsule o código de desenho em um loop for. Você deve acabar com o seguinte código canvas_Draw:
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. Execute o aplicativo novamente. Você deve ver um monte de texto, linhas e círculos com posições e tamanhos aleatórios.

Aplicar um efeito de imagem ao seu conteúdo

Os efeitos de imagem, também conhecidos como efeitos de filtro, são transformações gráficas aplicadas aos dados de pixel. Saturação, rotação de matiz e desfoque gaussiano são alguns dos efeitos de imagem comuns. Os efeitos de imagem podem ser encadeados, produzindo uma aparência visual sofisticada para um esforço mínimo.

Use efeitos de imagem fornecendo uma imagem de origem (o conteúdo com o qual você está começando), criando um efeito como GaussianBlurEffect, definindo propriedades como BlurAmount e desenhando a saída do efeito com DrawImage.

Para aplicar um efeito de imagem ao seu texto e formas, primeiro você precisa renderizar esse conteúdo em um CanvasCommandList. Esse objeto é utilizável como uma entrada para o efeito.

  1. Altere seu método canvas_Draw para usar o seguinte código:
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()));
    }
}

Assim como você obtém um CanvasDrawingSession de CanvasDrawEventArgs, com o qual você pode desenhar, você pode criar um CanvasDrawingSession a partir de CanvasCommandList. A única diferença é que, quando você desenha para a sessão de desenho da lista de comandos (clds), você não está renderizando diretamente para o CanvasControl. Em vez disso, a lista de comandos é um objeto intermediário que armazena os resultados da renderização para uso posterior.

Você deve ter notado o bloco using que encapsula a sessão de desenho da lista de comandos. As sessões de desenho implementam o IDisposable e devem ser descartadas quando você terminar de renderizar (o bloco using faz isso). O CanvasDrawingSession obtido automaticamente de CanvasDrawEventArgs fica fechado para você, mas você deve descartar todas as sessões de desenho que criou explicitamente.

  1. Por fim, defina o GaussianBlurEffect adicionando o seguinte código ao final do método canvas_Draw:
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. Execute o aplicativo novamente. Você deve ver suas linhas, textos e círculos com uma aparência desfocada.

Animar seu aplicativo com CanvasAnimatedControl

. O Win2D oferece a capacidade de atualizar e animar seu conteúdo em tempo real, por exemplo, ao alterar o raio do desfoque gaussiano com cada quadro. Para fazer isso, você usará CanvasAnimatedControl.

O CanvasControl é mais adequado para conteúdo gráfico estático. Ele só gera o evento Draw quando o conteúdo precisa ser atualizado ou redesenhado. Se você tiver alterado o conteúdo continuamente, cogite usar CanvasAnimatedControl no lugar. Os dois controles operam da mesma forma, com a exceção de que CanvasAnimatedControl gera o evento Draw periodicamente; por padrão, ele é chamado 60 vezes por segundo.

  1. Para alternar para CanvasAnimatedControl, vá para MainPage.xaml, exclua a linha CanvasControl e substitua-a pelo seguinte XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

Assim como no CanvasControl, permita que o Preenchimento Automático crie o manipulador de eventos Draw para você. Por padrão, o Visual Studio nomeará esse manipulador como canvas_Draw_1 porque canvas_Draw já existe; aqui, renomeamos o método canvas_AnimatedDraw para deixar claro que se trata de um evento diferente.

Além disso, você também está tratando um novo evento, CreateResources. Mais uma vez, permita que o Preenchimento Automático crie o manipulador.

Agora que seu aplicativo será redesenhado a 60 quadros por segundo, é mais eficiente criar seus recursos visuais do Win2D uma vez e reutilizá-los a cada quadro. É ineficiente criar um CanvasCommandList e desenhar 300 elementos nele 60 vezes por segundo quando o conteúdo permanecer estático. CreateResources é um evento que só será acionado quando o Win2D determinar que você precisa recriar seus recursos visuais, como quando a página é carregada.

  1. Volte para MainPage.xaml.cs. Localize o método canvas_Draw, que deve ter esta aparência:
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);
}

A maior parte desse código de desenho existente não precisa ser executada com cada quadro: a lista de comandos que contém o texto, linhas e círculos permanece a mesma em cada quadro; a única coisa que muda é o raio de desfoque. Portanto, você pode mover esse código "estático" para CreateResources.

Para isso, primeiro corte (CTRL+X) todo o conteúdo de canvas_Draw, exceto a última linha (args.DrawingSession.DrawImage(blur);). Agora você pode excluir o restante de canvas_Draw, pois ele não é mais necessário: lembre-se de que CanvasAnimatedControl tem seu próprio evento Draw distinto.

  1. Localize o método canvas_CreateResources gerado automaticamente:
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, 
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}

Cole (CTRL+V) seu código recortado anteriormente nesse método. Em seguida, mova a declaração de fora do corpo do método GaussianBlurEffect para que a variável se torne um membro da classe MainPage. Agora, o código será parecido com o seguinte:

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. Agora você pode animar o desfoque gaussiano. Localize o método canvas_DrawAnimated e adicione o seguinte código:
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);
}

Ele lê o tempo total decorrido fornecido por CanvasAnimatedDrawEventArgs e usa essa informação para calcular a quantidade de desfoque desejada; a função seno fornece uma variação interessante ao longo do tempo. Por fim, o GaussianBlurEffect é renderizado.

  1. Execute o aplicativo para ver a alteração do conteúdo desfocado ao longo do tempo.

Parabéns por concluir este tutorial de início rápido! Esperamos que você tenha visto como pode usar o Win2D para criar uma cena visual avançada e animada com apenas algumas linhas de código C# e XAML.