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:
- Instalar o Visual Studio
- Incluir o SDK da UWP (Plataforma Universal do Windows) ou do Windows (dependendo de suas necessidades), 17763+
- Se estiver usando a UWP, lembre-se também de habilitar o modo do desenvolvedor
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
- 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.
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.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">
- 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>
- 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 eventosDraw
:
<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
Agora, vamos para o code-behind C#. Abra
MainPage.xaml.cs
no Gerenciador de Soluções.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;
- 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.)
- 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.
- 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
- 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.
Abra
MainPage.xaml
e localize o elemento XAML da Página que contém o CanvasControl. Ele deve ser o primeiro elemento do arquivo.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">
- Vá para
MainPage.xaml.cs
e localize o manipulador de eventosPage_Unloaded
. Adicione o seguinte código:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
this.canvas.RemoveFromVisualTree();
this.canvas = null;
}
- 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
- É 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).
- 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
- 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);
}
- 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
.
- Por fim, encapsule o código de desenho em um loop
for
. Você deve acabar com o seguinte códigocanvas_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()));
}
- 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.
- 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.
- Por fim, defina o
GaussianBlurEffect
adicionando o seguinte código ao final do métodocanvas_Draw
:
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
- 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.
- Para alternar para
CanvasAnimatedControl
, vá paraMainPage.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.
- Volte para
MainPage.xaml.cs
. Localize o métodocanvas_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.
- 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
};
}
- 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.
- 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.
Windows developer