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 XAML em C#.
  • Desenhar texto e geometria.
  • Aplicar efeitos de filtro.
  • Anime o conteúdo do Win2D.
  • Siga as práticas recomendadas do Win2D.

Configurar seu computador de desenvolvimento

Configure seu computador com todas as ferramentas necessárias:

Criar um novo projeto Win2D

Siga as etapas no início rápido do Win2D "Olá, Mundo!" para criar um novo projeto usando o Win2D e adicionar uma referência ao pacote NuGet Win2D. Você pode usar o 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 um lugar para desenhar seus gráficos. Em um aplicativo XAML, a maneira mais simples de fazer isso é adicionar um CanvasControl à página XAML.

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

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

  2. Antes de adicionar o controle, primeiro você precisa informar ao XAML onde CanvasControl está definido. Para fazer isso, vá para a definição do elemento Page e adicione esta diretiva: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". Seu XAML agora 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 elemento como filho ao elemento grid raiz. Dê um nome ao controle, por exemplo, "tela". Seu XAML agora 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 Draw . CanvasControl aciona Draw sempre que seu aplicativo precisa desenhar ou redesenhar seu conteúdo. A maneira mais fácil é permitir que o Preenchimento Automático do Visual Studio ajude você. Na definição CanvasControl , comece a digitar um novo atributo para o Draw manipulador de eventos:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Observação

Depois de ter entrado em Draw=", o Visual Studio deverá abrir uma caixa solicitando que você permita que ela preencha automaticamente a 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 se você não usou o Preenchimento Automático; você pode adicionar manualmente o método do manipulador de eventos na próxima etapa.

Desenhar seu primeiro texto no Win2D

  1. Agora, vamos para o código C# atrás. Abra MainPage.xaml.cs no Gerenciador de Soluções.

  2. Na parte superior do arquivo C# estão 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 AutoComplete:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(Se você não usou 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 deslocar esse texto em 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, primeiro você deve adicionar algum código para garantir que seu aplicativo evite vazamentos de memória. A maioria dos aplicativos Win2D escritos em uma linguagem .NET e usando um controle Win2D como CanvasControl precisa seguir as etapas abaixo. Estritamente falando, seu aplicativo simples "Olá, mundo" não é afetado, mas essa é uma boa prática a seguir em geral.

Para obter mais informações, consulte Como evitar vazamentos 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 no arquivo.

  2. Adicione um manipulador para o evento Unloaded. 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"
    Unloaded="Page_Unloaded">
  1. Vá para MainPage.xaml.cs e encontre 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 Win2D, você precisará repetir as etapas acima para cada página XAML que contém um controle Win2D. No momento, seu aplicativo tem apenas um CanvasControl , portanto, você está pronto.

Desenhar algumas formas

  1. É tão 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 "Olá, mundo!" junto com um círculo verde e 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 usar pincéis. O Win2D fornece todas essas opções e muito mais e facilita o uso delas quando você quiser. Draw(...) Todos os métodos oferecem várias sobrecargas que podem aceitar parâmetros adicionais, como CanvasTextFormat (família de fontes, tamanho, etc.) e CanvasStrokeStyle (traços, pontos, terminações, etc.). Fique à vontade para explorar a superfície da API para saber mais sobre essas opções.

Gerar dinamicamente parâmetros de desenho

  1. Agora, vamos adicionar alguma variedade desenhando um monte de formas e texto com cores aleatórias.

Adicione o código a seguir à parte superior da 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 canvas_Draw método 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 valores A, R, G e B. A é alfa ou o nível de opacidade; nesse caso, você sempre deseja totalmente opaco (255).

DrawCircle e DrawLine operam de forma semelhante a DrawText.

  1. Por fim, embrulhe o código de desenho em um loop de for. Você deve obter 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 efeitos comuns de imagem. Os efeitos de imagem podem ser encadeados, produzindo aparência visual sofisticada para 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 pode ser usado como entrada para seu efeito.

  1. Altere seu canvas_Draw método 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 uma CanvasDrawingSession de CanvasDrawEventArgs com a qual você pode desenhar, você pode criar uma CanvasDrawingSession de um CanvasCommandList. A única diferença é que, quando você desenha para a sessão de desenho (clds) da lista de comandos, 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.

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

  1. Por fim, defina a 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, texto e círculos com uma aparência desfocada.

Animar seu aplicativo com CanvasAnimatedControl

. O Win2D permite atualizar e animar seu conteúdo em tempo real, por exemplo, alterando o raio do desfoque gaussiano a cada quadro. Para fazer isso, você usará CanvasAnimatedControl.

CanvasControl é mais adequado para conteúdo gráficos estáticos , ele só gera o Draw evento quando seu conteúdo precisa ser atualizado ou redesenhado. Se você tiver conteúdo em constante mudança, considere usar CanvasAnimatedControl ao invés. Os dois controles operam da mesma forma, exceto CanvasAnimatedControl gera o Draw evento 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 AutoComplete crie o Draw manipulador de eventos para você. Por padrão, o Visual Studio nomeará esse manipulador canvas_Draw_1 porque canvas_Draw já existe; aqui, renomeamos o método canvas_AnimatedDraw para deixar claro que esse é um evento diferente.

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

Agora que seu aplicativo será redesenhado a 60 quadros por segundo, é mais eficiente criar seus recursos visuais 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 permanece estático. CreateResources é um evento que é acionado somente quando o Win2D determina que você precisa recriar seus recursos visuais, como quando a página é carregada.

  1. Volte para MainPage.xaml.cs. Localize o canvas_Draw método 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 grande maioria 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 e a única coisa que muda é o raio de desfoque. Portanto, você pode mover esse código "estático" para CreateResources.

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

  1. Localize o método gerado canvas_CreateResources 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 GaussianBlurEffect método 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 canvas_DrawAnimated método 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);
}

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

  1. Execute o aplicativo para ver como o conteúdo desfocado muda ao longo do tempo.

Parabéns por concluir este tutorial de início rápido! Espero 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.