Freigeben über


Erstellen einer einfachen Win2D-App

In diesem Tutorial werden einige der grundlegenden Zeichenfunktionen von Win2D vorgestellt. Sie lernen Folgendes:

  • Fügen Sie Win2D zu einem C#-XAML-Windows-Projekt hinzu.
  • Zeichnen Sie Text und Geometrie.
  • Wenden Sie Filtereffekte an.
  • Animieren Sie Win2D-Inhalte.
  • Befolgen Sie bewährte Methoden für Win2D.

Einrichten eines Entwickler-Computers

Stellen Sie sicher, dass Sie Ihren Computer mit allen erforderlichen Tools einrichten:

Erstellen eines neuen Win2D-Projekts

Führen Sie die Schritte in der Win2D-Schnellstartanleitung „Hello, World!“ aus, um ein neues Projekt mit Win2D zu erstellen und einen Verweis auf das Win2D NuGet-Paket hinzuzufügen. Sie können WinUI 3 (Windows App SDK) oder die Universelle Windows-Plattform (UWP) verwenden.

Hinzufügen eines Win2D CanvasControl-Elements zum XAML-Code Ihrer App

  1. Um Win2D zu verwenden, benötigen Sie einen Ort, an dem Sie ihre Grafiken zeichnen können. In einer XAML-App ist hierfür die einfachste Möglichkeit, Ihrer XAML-Seite ein CanvasControl hinzuzufügen.

Bevor Sie fortfahren, stellen Sie zunächst sicher, dass die Architekturoption des Projekts auf x86 oder x64nicht auf Any CPU eingestellt ist. Win2D wird in C++ implementiert und daher müssen Projekte, die Win2D verwenden, auf eine bestimmte CPU-Architektur ausgerichtet sein.

  1. Navigieren Sie zu MainPage.xaml in Ihrem Projekt, indem Sie im Projektmappen-Explorer darauf doppelklicken. Dadurch wird die Datei geöffnet. Der Einfachheit halber können Sie auf der Registerkarte Designer auf die Schaltfläche XAML doppelklicken. Hierdurch wird der Visual Designer ausgeblendet, und der gesamte Speicherplatz wird für die Codeansicht reserviert.

  2. Bevor Sie das Steuerelement hinzufügen, müssen Sie zuerst XAML mitteilen, wo CanvasControl definiert ist. Wechseln Sie dazu zur Definition des Elements Seite, und fügen Sie diese Anweisung hinzu: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". Ihr XAML sollte jetzt wie folgt aussehen:

<Page
    ...
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">
  1. Fügen Sie nun dem Stammelement Raster ein neues canvas:CanvasControl als untergeordnetes Element hinzu. Geben Sie dem Steuerelement einen Namen, z. B. „canvas“. Ihr XAML sollte jetzt wie folgt aussehen:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasControl x:Name="canvas"/>
</Grid>
  1. Definieren Sie als nächstes einen Ereignishandler für das Ereignis Zeichnen. CanvasControl löst Draw aus, wenn Ihre App den Inhalt zeichnen oder neu zeichnen muss. Die einfachste Möglichkeit besteht darin, die Funktion AutoVervollständigen von Visual Studio helfen zu lassen. Beginnen Sie in der CanvasControl-Definition mit der Eingabe eines neuen Attributs für den Draw-Ereignishandler:
<canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

Hinweis

Nachdem Sie sich bei Draw=" angemeldet haben, sollte Visual Studio ein Feld öffnen, in dem Sie aufgefordert werden, die richtige Definition für den Ereignishandler automatisch auszufüllen. Drücken Sie die TAB-Taste, um den Standardereignishandler von Visual Studio zu akzeptieren. Dadurch wird auch automatisch eine ordnungsgemäß formatierte Ereignishandlermethode in Ihrem CodeBehind („MainPage.xaml.cs“) hinzugefügt. Machen Sie sich keine Sorgen, wenn Sie AutoVervollständigen nicht verwendet haben. Sie können die Ereignishandlermethode im nächsten Schritt manuell hinzufügen.

Zeichnen des ersten Texts in Win2D

  1. Jetzt gehen wir zum C#-CodeBehind. Öffnen Sie MainPage.xaml.cs im Projektmappen-Explorer.

  2. Oben in der C#-Datei befinden sich verschiedene Namespacedefinitionen. Fügen Sie die folgenden Namespaces hinzu:

using Windows.UI;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
  1. Als Nächstes sollte der folgende leere Ereignishandler angezeigt werden, der von AutoVervollständigen eingefügt wurde:
private void canvas_Draw(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
}

(Wenn Sie AutoVervollständigen im vorherigen Schritt nicht verwendet haben, fügen Sie diesen Code jetzt hinzu.)

  1. Der Parameter CanvasDrawEventArgs macht das Element DrawingSession verfügbar, das vom Typ CanvasDrawingSession ist. Diese Klasse bietet die meisten grundlegenden Zeichenfunktionen in Win2D: Sie verfügt über Methoden wie CanvasDrawingSession.DrawRectangle, CanvasDrawingSession.DrawImage und die Methode, die Sie zum Zeichnen von Text benötigen, CanvasDrawingSession.DrawText.

Fügen Sie der canvas_Draw-Methode folgenden Code hinzu:

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

Das erste Argument ist die Zeichenfolge, nämlich "Hello, World!", die Win2D anzeigen soll. Die beiden "100"-Elemente weisen Win2D an, diesen Text um 100 DIPs (geräteunabhängige Pixel) nach rechts und unten zu verschieben. Zuletzt definiert Colors.Black die Farbe des Texts.

  1. Jetzt können Sie Ihre erste Win2D-App ausführen. Drücken Sie F5, um zu kompilieren und zu starten. Sie sollten ein leeres Fenster mit "Hello, world!" in Schwarz sehen.

Ordnungsgemäßes Löschen von Win2D-Ressourcen

  1. Bevor Sie weiter andere Arten von Inhalten zeichnen, sollten Sie zuerst Code hinzufügen, um sicherzustellen, dass Ihre App Speicherverluste vermeidet. Die meisten Win2D-Anwendungen, die in einer .NET-Sprache geschrieben wurden und, wie CanvasControl, ein Win2D-Steuerelement verwenden, müssen die folgenden Schritte ausführen. Streng genommen ist Ihre einfache "Hello, world"-App nicht betroffen, aber dies ist generell eine bewährte Methode.

Weitere Informationen finden Sie unter Vermeiden von Speicherlecks.

  1. Öffnen Sie MainPage.xaml und suchen Sie das Page-XAML-Element, das Ihr CanvasControl enthält. Es sollte das erste Element in der Datei sein.

  2. Fügen Sie einen Handler für das Unloaded-Ereignis hinzu. Der XAML-Code sollte wie folgt aussehen:

<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. Wechseln Sie zu MainPage.xaml.cs und suchen Sie den Page_Unloaded-Ereignishandler. Fügen Sie den folgenden Code hinzu:
void Page_Unloaded(object sender, RoutedEventArgs e)
{
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;
}
  1. Wenn Ihre App mehrere Win2D-Steuerelemente enthält, müssen Sie die obigen Schritte für jede XAML-Seite wiederholen, die ein Win2D-Steuerelement enthält. Ihre App verfügt derzeit nur über ein einziges CanvasControl, sodass Sie fertig sind.

Zeichnen einiger Formen

  1. Es ist genauso einfach, Ihrer App 2D-Geometrie hinzuzufügen. Fügen Sie am Ende von canvas_Draw folgenden Code hinzu:
args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

Die Argumente für diese beiden Methoden ähneln DrawText. Ein Kreis wird durch einen Mittelpunkt (125, 125), einen Radius (100) und eine Farbe (Grün) definiert. Eine Linie wird durch einen Anfang (0, 0), ein Ende (50, 200) und eine Farbe (Rot) definiert.

  1. Drücken Sie F5, um die App auszuführen. Sie sollten "Hello, world!" zusammen mit einem grünen Kreis und einer roten Linie sehen.

Möglicherweise fragen Sie sich, wie Sie erweiterte Zeichnungsoptionen wie Linienstärke und Striche oder komplexere Fülloptionen wie die Verwendung von Pinseln steuern können. Win2D bietet alle diese Optionen und vieles mehr und erleichtert ihnen die Verwendung bei Bedarf. Alle Draw(...)-Methoden bieten viele Überladungen, die zusätzliche Parameter wie z. B. CanvasTextFormat (Schriftartfamilie, Schriftgröße usw.) und CanvasStrokeStyle (Striche, Punkte, Endcaps usw.) akzeptieren können. Sie können die API-Oberfläche erkunden, um mehr über diese Optionen zu erfahren.

Dynamisches Generieren von Zeichnungsparametern

  1. Jetzt fügen wir eine gewisse Vielfalt hinzu, indem wir eine Reihe von Formen und Text mit zufälligen Farben zeichnen.

Fügen Sie oben in der MainPage-Klasse den folgenden Code hinzu. Dies ist eine Hilfsfunktion zum Generieren von Zufallswerten, die Sie beim Zeichnen verwenden werden:

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. Ändern Sie die canvas_Draw-Methode so, dass sie mit diesen zufälligen Parametern gezeichnet wird:
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()));
}

Lassen Sie uns aufschlüsseln, wie sich DrawText geändert hat. "Hello, World!" bleibt unverändert. Die x- und y-Offsetparameter wurden durch einen einzelnen System.Numerics.Vector2 ersetzt, der von RndPosition generiert wird. Schließlich können Sie anstelle einer vordefinierten Farbe Color.FromArgb eine Farbe mithilfe von A-, R-, G- und B-Werten definieren. A ist Alpha oder die Deckkraftstufe; in diesem Fall möchten Sie immer vollständig undurchsichtig (255).

DrawCircle und DrawLine funktionieren ähnlich wie DrawText.

  1. Umschließen Sie zuletzt den Zeichnungscode in einer for-Schleife. Sie sollten mit den folgenden canvas_Draw-Code erhalten:
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. Führen Sie die App erneut aus. Sie sollten eine ganze Reihe von Text, Zeilen und Kreisen mit zufälligen Positionen und Größen sehen.

Anwenden eines Bildeffekts auf Ihre Inhalte

Bildeffekte, auch als Filtereffekte bezeichnet, sind grafische Transformationen, die auf Pixeldaten angewendet werden. Sättigung, Farbtondrehung und Gaußscher Weichzeichner sind einige häufig angewandte Bildeffekte. Bildeffekte können miteinander verkettet werden, wodurch mit minimalen Aufwand entsteht ein anspruchsvolles visuelles Erscheinungsbild.

Sie verwenden Bildeffekte, indem Sie ein Quellbild (den Inhalt, mit dem Sie beginnen) bereitstellen, einen Effekt wie GaussianBlurEffect, das Festlegen von Eigenschaften wie BlurAmount, und dann die Ausgabe des Effekts mit DrawImage.

Um einen Bildeffekt auf Text und Formen anzuwenden, müssen Sie diesen Inhalt zuerst in einer CanvasCommandList rendern. Dieses Objekt kann als Eingabe für Ihren Effekt verwendet werden.

  1. Ändern Sie die canvas_Draw-Methode so, dass sie den folgenden Code verwendet:
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()));
    }
}

Genau wie sie ein CanvasDrawingSession aus CanvasDrawEventArgs erhalten, mit dem Sie zeichnen können, können Sie ein CanvasDrawingSession aus einem CanvasCommandList erstellen. Der einzige Unterschied besteht darin, dass Sie beim Zeichnen auf die Zeichnungssitzung der Befehlsliste (clds) und nicht direkt auf CanvasControl rendern. Stattdessen ist die Befehlsliste ein Zwischenobjekt, das die Ergebnisse des Renderns für die spätere Verwendung speichert.

Möglicherweise haben Sie den using-Block bemerkt, der die Zeichnungssitzung der Befehlsliste umschließt. Zeichnungssitzungen implementieren IDisposable und müssen verworfen werden, wenn Sie mit dem Rendern fertig sind (der using-Block führt dies aus). Das CanvasDrawingSession, von dem Sie automatisch CanvasDrawEventArgs abrufen, wird für Sie geschlossen, Sie müssen jedoch alle Zeichnungssitzungen löschen, die Sie explizit erstellt haben.

  1. Definieren Sie schließlich GaussianBlurEffect, indem Sie folgenden Code am Ende der canvas_Draw-Methode hinzufügen:
GaussianBlurEffect blur = new GaussianBlurEffect();
blur.Source = cl;
blur.BlurAmount = 10.0f;
args.DrawingSession.DrawImage(blur);
  1. Führen Sie die App erneut aus. Sie sollten Ihre Zeilen, Texte und Kreise in einer verschwommenen Erscheinung sehen.

Animieren Ihrer App mit CanvasAnimatedControl

. Win2D bietet Ihnen die Möglichkeit, Ihre Inhalte in Echtzeit zu aktualisieren und zu animieren, z. B. durch Ändern des Weichzeichner-Radius des Gaußschen Weichzeichners mit jedem Frame. Dazu verwenden Sie CanvasAnimatedControl.

CanvasControl eignet sich am besten für statische Grafikinhalte – es löst das Draw-Ereignis nur aus, wenn Ihre Inhalte aktualisiert oder neu gezeichnet werden müssen. Wenn Sie sich ständig ändernde Inhalte haben, sollten Sie stattdessen die Verwendung CanvasAnimatedControl in Betracht ziehen. Die beiden Steuerelemente funktionieren sehr ähnlich, außer dass CanvasAnimatedControl regelmäßig das Draw-Ereignis auslöst. Standardmäßig wird es 60 Mal pro Sekunde aufgerufen.

  1. Zum Wechseln zu CanvasAnimatedControl, gehen Sie zu MainPage.xaml, löschen Sie die CanvasControl-Zeile, und ersetzen Sie sie durch den folgenden XAML-Code:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <canvas:CanvasAnimatedControl x:Name="canvas" Draw="canvas_DrawAnimated" CreateResources="canvas_CreateResources"/>
</Grid>

Lassen Sie AutoVervollständigen, genau wie bei CanvasControl, Ihnen den Draw-Ereignishandler erstellen. Standardmäßig benennt Visual Studio diesen Handler canvas_Draw_1, da canvas_Draw bereits vorhanden ist. Hier haben wir die Methode in canvas_AnimatedDraw umbenannt, um deutlich zu machen, dass es sich um ein anderes Ereignis handelt.

Darüber hinaus behandeln Sie auch ein neues Ereignis, nämlich CreateResources. Lassen Sie AutoVervollständigen den Handler erneut erstellen.

Da Ihre App jetzt mit 60 Frames pro Sekunde neu gezeichnet wird, ist es effizienter, Ihre visuellen Win2D-Ressourcen einmal zu erstellen und mit jedem Frame wiederzuverwenden. Es ist ineffizient, ein CanvasCommandList zu erstellen und 300 Elemente 60mal pro Sekunde hineinzuzeichnen, wenn der Inhalt statisch bleibt. CreateResources ist ein Ereignis, das nur ausgelöst wird, wenn Win2D bestimmt, dass Sie ihre visuellen Ressourcen neu erstellen müssen, z. B. wenn die Seite geladen wird.

  1. Wechseln Sie wieder zu MainPage.xaml.cs. Suchen Sie Ihre canvas_Draw-Methode, die wie folgt aussehen soll:
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);
}

Der Großteil dieses vorhandenen Draw-Codes muss nicht mit jedem Frame ausgeführt werden: Die Befehlsliste, die den Text, die Zeilen und Kreise enthält, bleibt mit jedem Frame gleich, und das einzige, was sich ändert, ist der Weichzeichnerradius. Daher können Sie diesen „statischen“ Code in CreateResources verschieben.

Dazu schneiden Sie zuerst den gesamten Inhalt von canvas_Draw(STRG+X), mit Ausnahme der letzten Zeile (args.DrawingSession.DrawImage(blur);), aus. Sie können jetzt den Rest von canvas_Draw löschen, da er nicht mehr benötigt wird: Erinnern Sie sich, dass CanvasAnimatedControl über ein eigenes eindeutiges Draw-Ereignis verfügt.

  1. Suchen Sie die automatisch generierte canvas_CreateResources-Methode:
private void canvas_CreateResources(
    Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, 
    Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
{}

Fügen Sie ihren zuvor ausgeschnittenen Code in diese Methode ein (STRG+V). Verschieben Sie als Nächstes die Deklaration von GaussianBlurEffect außerhalb des Methodentexts, damit die Variable ein Element der MainPage-Klasse wird. Ihr Code sollte nun wie folgt aussehen:

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. Jetzt können Sie den Gaußschen Weichzeichner animieren. Suchen Sie die canvas_DrawAnimated-Methode, und fügen Sie den folgenden Code hinzu:
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);
}

Dies liest die gesamte verstrichene Zeit, die von CanvasAnimatedDrawEventArgs bereitgestellt wird, und verwendet diese, um die gewünschte Weichzeichnermenge zu berechnen. Die Sinusfunktion bietet eine interessante Variation im Laufe der Zeit. Schließlich ist GaussianBlurEffect vollständig gerendert.

  1. Führen Sie die App aus, um die verschwommenen Inhalte im Zeitverlauf zu sehen.

Damit haben Sie dieses Tutorial erfolgreich abgeschlossen! Hoffentlich haben Sie gesehen, wie Sie Win2D verwenden können, um eine umfangreiche, animierte visuelle Szene mit nur wenigen Zeilen C# und XAML-Code zu erstellen.