Condividi tramite


Creare una semplice app Win2D

Questa esercitazione presenta alcune delle funzionalità di disegno di base di Win2D. Si apprenderà come:

  • Aggiungere Win2D a un progetto Windows XAML C#.
  • Disegnare testo e geometria.
  • Applicare effetti di filtro.
  • Anima il tuo contenuto Win2D.
  • Seguire le procedure consigliate di Win2D.

Configurare il computer di sviluppo

Assicurarsi di configurare il computer con tutti gli strumenti necessari:

  • Installa Visual Studio
    • Includere la piattaforma UWP o Windows SDK (a seconda delle esigenze), 17763+
  • Se si usa UWP, assicurarsi di abilitare anche la modalità sviluppatore

Creare un nuovo progetto Win2D

Seguire i passaggi della guida introduttiva "Hello, World!" win2D per creare un nuovo progetto con Win2D e aggiungere un riferimento al pacchetto NuGet Win2D. Puoi usare WinUI 3 (Windows App SDK) o la piattaforma UWP (Universal Windows Platform).

Aggiungere un oggetto CanvasControl Win2D al codice XAML dell'app

  1. Per usare Win2D, è necessario un punto per disegnare la grafica. In un'app XAML, il modo più semplice per eseguire questa operazione consiste nell'aggiungere canvasControl alla pagina XAML.

Prima di continuare, assicurati che l'opzione Architettura del progetto sia impostata su x86 o x64 e su , non su a Any CPU. Win2D viene implementato in C++, quindi i progetti che usano Win2D devono essere destinati a un'architettura di CPU specifica.

  1. Navigare a MainPage.xaml nel progetto facendo doppio clic su di esso in Esplora Soluzioni. Verrà aperto il file. Per praticità, puoi fare doppio clic sul pulsante XAML nella scheda Progettazione; in questo modo verrà nascosta la finestra di progettazione visiva e verrà riservato tutto lo spazio per la visualizzazione codice.

  2. Prima di aggiungere il controllo, devi prima indicare a XAML dove è definito CanvasControl . A tale scopo, passare alla definizione dell'elemento Page e aggiungere questa direttiva: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". Il codice XAML dovrebbe ora essere simile al seguente:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">
  1. Aggiungere ora un nuovo canvas:CanvasControl elemento come elemento figlio all'elemento Grid radice. Assegna un nome al controllo, ad esempio "canvas". Il codice XAML dovrebbe ora essere simile al seguente:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. Definire quindi un gestore eventi per l'evento Draw . CanvasControl genera Draw ogni volta che l'app deve disegnare o ridisegnare il contenuto. Il modo più semplice è farsi aiutare dal completamento automatico di Visual Studio. Nella definizione CanvasControl iniziare a digitare un nuovo attributo per il Draw gestore eventi:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Annotazioni

Dopo aver immesso il testo in Draw=", Visual Studio dovrebbe visualizzare una finestra che chiede se si desidera completare automaticamente la definizione corretta per il gestore eventi. Premere TAB per accettare il gestore eventi predefinito di Visual Studio. Verrà aggiunto automaticamente anche un metodo del gestore eventi formattato correttamente nel code-behind ('MainPage.xaml.cs''). Non preoccuparti se non hai usato il completamento automatico; è possibile aggiungere manualmente il metodo del gestore eventi nel passaggio successivo.

Disegnare il primo testo in Win2D

  1. A questo punto, passiamo al codice sottostante C#. Apri MainPage.xaml.cs da Esplora soluzioni.

  2. Nella parte superiore del file C# sono presenti varie definizioni di namespace. Aggiungere i namespace seguenti:

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. Verrà quindi visualizzato il gestore eventi vuoto seguente che è stato inserito da AutoComplete:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

Se il completamento automatico non è stato usato nel passaggio precedente, aggiungere ora questo codice.

  1. Il parametro CanvasDrawEventArgs espone un membro DrawingSession, che corrisponde al tipo CanvasDrawingSession. Questa classe offre la maggior parte delle funzionalità di disegno di base in Win2D: include metodi come CanvasDrawingSession.DrawRectangle, CanvasDrawingSession.DrawImage e il metodo che è necessario disegnare testo, CanvasDrawingSession.DrawText.

Aggiungere al metodo canvas_Draw il codice seguente:

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

Il primo argomento, "Hello, World!", è la stringa che si vuole visualizzare da Win2D. I due "100" indicano a Win2D di sfalsare questo testo di 100 DIP (pixel indipendenti dal dispositivo) a destra e verso il basso. Infine, Colors.Black definisce il colore del testo.

  1. Ora sei pronto per eseguire la tua prima app Win2D. Premere il tasto F5 per compilare e avviare. Dovrebbe essere visualizzata una finestra vuota con "Hello, world!" in nero.

Eliminare correttamente le risorse Win2D

  1. Prima di continuare a disegnare altri tipi di contenuto, devi prima aggiungere codice per assicurarti che l'app eviti perdite di memoria. La maggior parte delle applicazioni Win2D scritte in un linguaggio .NET e l'uso di un controllo Win2D come CanvasControl devono seguire la procedura seguente. In senso stretto, la tua semplice app "Hello, world" non è interessata, ma questa è una buona pratica da seguire in generale.

Per altre informazioni, vedere Evitare perdite di memoria.

  1. Aprire MainPage.xaml e trovare l'elemento XAML Page che contiene il tuo CanvasControl. Deve essere il primo elemento del file.

  2. Aggiungere un gestore per l'evento Unloaded. Il codice XAML dovrebbe essere simile al seguente:

<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. Vai a MainPage.xaml.cs e trova il gestore eventi Page_Unloaded. Aggiungere il codice seguente:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. Se la tua app contiene più controlli Win2D, devi ripetere i passaggi precedenti per ogni pagina XAML che contiene un controllo Win2D. Al momento, l'app ha solo un singolo CanvasControl, quindi hai finito.

Disegnare alcune forme

  1. È altrettanto semplice aggiungere geometria 2D all'app. Aggiungere il codice seguente alla fine di canvas_Draw:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

Gli argomenti di questi due metodi sono simili a DrawText. Un cerchio è definito da un punto centrale (125, 125), un raggio (100) e un colore (verde). Una linea è definita da un inizio (0, 0), una fine (50, 200) e un colore (rosso).

  1. Premere F5 per eseguire l'app. Verrà visualizzato "Hello, world!" insieme a un cerchio verde e a una linea rossa.

Ci si potrebbe chiedere come controllare opzioni di disegno più avanzate, ad esempio spessore linea e trattini, o opzioni di riempimento più complesse come l'uso di pennelli. Win2D offre tutte queste opzioni e altro ancora e semplifica l'uso quando vuoi. Tutti i metodi di Draw(...) offrono molti sovraccarichi che possono accettare parametri aggiuntivi come CanvasTextFormat (famiglia di caratteri, dimensioni, ecc.) e CanvasStrokeStyle (trattini, punti, terminazioni, ecc.). È possibile esplorare l'area API per altre informazioni su queste opzioni.

Generare dinamicamente parametri di disegno

  1. A questo punto, aggiungiamo un po' di varietà disegnando una serie di forme e testo con colori casuali.

Aggiungi il codice seguente all'inizio della classe MainPage. Questa è la funzionalità helper per generare valori casuali che verranno usati durante il disegno:

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. Modificare il canvas_Draw metodo per disegnare usando questi parametri casuali:
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()));
}

Di seguito viene descritto come DrawText è cambiato. "Hello, World!" rimane uguale a prima. I parametri di offset x e y sono stati sostituiti con un singolo oggetto System.Numerics.Vector2 generato da RndPosition. Infine, invece di usare un colore predefinito, Color.FromArgb consente di definire un colore usando i valori A, R, G e B. A è alfa o livello di opacità; in questo caso si dovrebbe avere opaco completo (255).

DrawCircle e DrawLine funzionano in modo analogo a DrawText.

  1. Infine, racchiudi il codice di disegno in un ciclo for. Dovresti arrivare al seguente codice 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. Eseguire di nuovo l'app. Dovrebbe essere visualizzato un intero gruppo di testo, linee e cerchi con posizioni e dimensioni casuali.

Applicare un effetto immagine al contenuto

Gli effetti immagine, noti anche come effetti filtro, sono trasformazioni grafiche applicate ai dati pixel. La saturazione, la rotazione delle tonalità e la sfocatura gaussiana sono alcuni effetti di immagine comuni. Gli effetti immagine possono essere concatenati, producendo un aspetto visivo sofisticato per un lavoro minimo.

Gli effetti immagine vengono usati fornendo un'immagine di origine (il contenuto da cui si parte), applicando un effetto come GaussianBlurEffect, impostando proprietà come BlurAmount e quindi disegnando l'output dell'effetto con DrawImage.

Per applicare un effetto immagine al testo e alle forme, è necessario prima eseguire il rendering del contenuto in canvasCommandList. Questo oggetto è utilizzabile come input per il tuo effetto.

  1. Modificare il canvas_Draw metodo per usare il codice seguente:
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()));
    }
}

Proprio come si ottiene un CanvasDrawingSession oggetto da CanvasDrawEventArgs cui è possibile disegnare, è possibile creare un oggetto CanvasDrawingSession da un oggetto CanvasCommandList. L'unica differenza è che quando si disegna nella sessione di disegno dell'elenco comandi (clds), non si esegue direttamente il rendering in CanvasControl. L'elenco dei comandi è invece un oggetto intermedio che archivia i risultati del rendering per un uso successivo.

Potresti aver notato il blocco using che avvolge la sessione di disegno dell'elenco dei comandi. Le sessioni di disegno implementano IDisposable e devono essere eliminate al termine del rendering (il using blocco esegue questa operazione). Il CanvasDrawingSession ottenuto da CanvasDrawEventArgs automaticamente viene chiuso automaticamente, ma è necessario eliminare tutte le sessioni di disegno create in modo esplicito.

  1. Infine, definire GaussianBlurEffect aggiungendo il codice seguente alla fine del canvas_Draw metodo :
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. Eseguire di nuovo l'app. Dovresti vedere le righe, il testo e i cerchi con un aspetto sfocato.

Animare l'app con CanvasAnimatedControl

. Win2D ti offre la possibilità di aggiornare e animare il contenuto in tempo reale, ad esempio modificando il raggio di sfocatura del blur gaussiano con ogni fotogramma. A tale scopo, si userà CanvasAnimatedControl.

CanvasControl è particolarmente adatto per il contenuto grafico statico, ma genera solo l'evento Draw quando il contenuto deve essere aggiornato o ridisegnato. Se il contenuto cambia continuamente, dovresti considerare di usare CanvasAnimatedControl. I due controlli funzionano in modo molto simile, eccetto che CanvasAnimatedControl genera l'evento Draw a intervalli regolari; per impostazione predefinita viene chiamato sessanta volte al secondo.

  1. Per selezionare CanvasAnimatedControl, vai a MainPage.xaml, elimina la riga CanvasControl e sostituiscila con il seguente codice XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

Proprio come con CanvasControl, lascia che il completamento automatico crei il gestore eventi Draw per te. Per impostazione predefinita, Visual Studio denomina questo gestore canvas_Draw_1 perché canvas_Draw esiste già. In questo caso è stato rinominato il metodo canvas_AnimatedDraw per chiarire che si tratta di un evento diverso.

Inoltre, si gestisce anche un nuovo evento, CreateResources. Ancora una volta, lasciare che il completamento automatico crei il gestore.

Ora che l'app verrà ridisegnata a 60 fotogrammi al secondo, è più efficiente creare le risorse visive Win2D una volta e riutilizzarle con ogni fotogramma. È inefficiente creare un oggetto CanvasCommandList e disegnare 300 elementi in esso 60 volte al secondo quando il contenuto rimane statico. CreateResources è un evento generato solo quando Win2D determina che è necessario ricreare le risorse visive, ad esempio quando la pagina viene caricata.

  1. Passare nuovamente a MainPage.xaml.cs. Trova il tuo metodo canvas_Draw, che dovrebbe apparire come segue:
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 maggior parte di questo codice di disegno esistente non deve essere eseguita con ogni fotogramma: l'elenco di comandi contenente il testo, le righe e i cerchi rimane invariato con ogni fotogramma e l'unica cosa che cambia è il raggio di sfocatura. Pertanto, è possibile spostare questo codice "statico" in CreateResources.

A tale scopo, tagliare prima (CTRL+X) l'intero contenuto di canvas_Draw, ad eccezione dell'ultima riga (args.DrawingSession.DrawImage(blur);). È ora possibile eliminare il resto di canvas_Draw perché non è più necessario: ricordare che CanvasAnimatedControl ha un proprio evento distinto Draw .

  1. Trovare il metodo generato canvas_CreateResources automaticamente:
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, 
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}

Incolla (CTRL+V) il codice che hai tagliato precedentemente in questo metodo. Spostare quindi la dichiarazione di GaussianBlurEffect all'esterno del corpo del metodo in modo che la variabile diventi un membro della classe MainPage. Il codice dovrebbe ora essere simile al seguente:

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. Ora puoi animare la sfocatura gaussiana. Trovare il canvas_DrawAnimated metodo e aggiungere il codice seguente:
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);
}

Questo rileva il tempo totale trascorso fornito da CanvasAnimatedDrawEventArgs e lo usa per calcolare la quantità di sfocatura desiderata; la funzione seno fornisce una variazione interessante nel corso del tempo. Infine, viene eseguito il rendering del GaussianBlurEffect.

  1. Avvia l'app per vedere come il contenuto sfocato cambia nel tempo.

Congratulazioni per aver completato questa esercitazione introduttiva. Speriamo di aver visto come usare Win2D per creare una scena visiva ricca e animata con poche righe di codice C# e XAML.