Click or drag to resize
Quick start

This quick start tutorial introduces some of the basic capabilities of Win2D. You will learn how to:

  • Add Win2D to a XAML C# Windows project
  • Draw text and geometry
  • Apply filter effects
  • Animate your Win2D content
  • Follow Win2D best practices

Install Visual Studio

  • If you don't have a supported version of Visual Studio installed, follow the steps here: Getting Set Up.

Create a new project with Win2D

  1. Launch Visual Studio, and create a new project: File → New → Project.

  2. Select Installed → Templates → Visual C# → ProjectReunion → WinUI → Blank App, Packaged (WinUI in Desktop).

  3. Give the project a name, choose a location, and create it.

  4. Win2D is released as a Nuget.org package and needs to be installed before you can use it. Launch the NuGet Package Manager by going to Tools → NuGet Package Manager → Manage NuGet Packages for Solution.

  5. Search for "Win2D" and select Microsoft.Graphics.Win2D.

    Finally, click Install. If you are prompted to review changes, click OK. If you are presented with the Win2D license terms, click I Accept.

    Win2D is now installed in your project.

Add a Win2D CanvasControl to your app's XAML

  1. In order to use Win2D, you need somewhere to draw your graphics. In a XAML app, the simplest way to do this is to add a CanvasControl to your XAML Window.

    Before you continue, first ensure that the project's Architecture option is set to x86 or x64 and NOT to Any CPU. Win2D is implemented in C++ and therefore projects that use Win2D need to be targeted to a specific CPU architecture.

  2. Navigate to MainWindow.xaml in your project by double clicking on it in Solution Explorer. This will open the file. For convenience, you can double click on the XAML button in the Designer tab; this will hide the visual designer and reserve all of the space for the code view.

  3. Before you add the control, you first have to tell XAML where CanvasControl is defined. To do this, go to the definition of the Window element, and add this statement: xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml". Your XAML should now look like this:

    XAML
    <Window
        ...
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
        mc:Ignorable="d">
  4. Now, add a new canvas:CanvasControl as a child element to the root Grid element. Give the control a name, e.g. "canvas". Your XAML should now look like this:

    XAML
    <Grid>
        <canvas:CanvasControl x:Name="canvas"/>
    </Grid>
  5. Next, define an event handler for the Draw event. CanvasControl raises Draw whenever your app needs to draw or redraw its content. The easiest way is to let Visual Studio AutoComplete assist you. In the CanvasControl definition, begin typing a new attribute for the Draw event handler:

    XAML
    <canvas:CanvasControl x:Name="canvas" Draw="canvas_Draw" />

    Once you have entered in Draw=", Visual Studio should pop up a box prompting you to let it automatically fill out the right definition for the event handler. Press TAB to accept Visual Studio's default event handler. This will also automatically add a correctly formatted event handler method in your code behind (MainWindow.xaml.cs). Don't worry if you didn't use AutoComplete; you can manually add the event handler method in the next step.

Draw your first text in Win2D

  1. Now, let's go to the C# code behind. Open MainWindow.xaml.cs from Solution Explorer.

  2. At the top of the C# file are various namespace definitions. Add the following namespaces:

    C#
    using Windows.UI;
    using System.Numerics;
    using Microsoft.Graphics.Canvas;
    using Microsoft.Graphics.Canvas.Effects;
  3. Next, you should see the following blank event handler which was inserted by AutoComplete:

    C#
    private void canvas_Draw(
        Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,
        Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
    {}

    (If you didn't use AutoComplete in the previous step, add this code now.)

  4. The CanvasDrawEventArgs parameter exposes a member, DrawingSession, which is of the type CanvasDrawingSession. This class provides most of the basic drawing functionality in Win2D: it has methods such as CanvasDrawingSessionDrawRectangle, CanvasDrawingSessionDrawImage, and the method you need to draw text, CanvasDrawingSessionDrawText.

    Add the following code to the canvas_Draw method:

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

    The first argument, "Hello, World!", is the string that you want Win2D to display. The two "100"s tell Win2D to offset this text by 100 DIPs (device-independent pixels) to the right and down. Finally, "Colors.Black" defines the color of the text.

  5. Now you are ready to run your first Win2D app. Press the F5 key to compile and launch. You should see an empty window with "Hello, world!" in black.

Correctly dispose of Win2D resources

  1. Before continuing on to draw other kinds of content, you first should add some code to ensure your app avoids memory leaks. Most Win2D applications written in a .NET language and using a Win2D control like CanvasControl need to follow the below steps. Strictly speaking, your simple "Hello, world" app is not affected, but this is a good practice to follow in general.

    For more information, see Avoiding memory leaks.

  2. Open MainWindow.xaml and find the Window XAML element that contains your CanvasControl. It should be the first element in the file.

  3. When you are ready to release the resources held by your Canvas, call the following code from your MainWindow.xaml.cs:

    C#
    this.canvas.RemoveFromVisualTree();
    this.canvas = null;

  4. If your app contains multiple Win2D controls, then you need to repeat the above steps for each Win2D control. Your app currently only has a single CanvasControl so you're all done.

Draw some shapes

  1. It's just as easy to add 2D geometry to your app. Add the following code to the end of canvas_Draw:

    C#
    args.DrawingSession.DrawCircle(125, 125, 100, Colors.Green);
    args.DrawingSession.DrawLine(0, 0, 50, 200, Colors.Red);

    The arguments to these two methods are similar to DrawText. A circle is defined by a center point (125, 125), a radius (100), and a color (Green). A line is defined by a beginning (0, 0), an end (50, 200) and a color (Red).

  2. Now, press F5 to run the app. You should see "Hello, world!" along with a green circle and red line.

    You may be wondering how to control more advanced drawing options, such as line thickness and dashes, or more complex fill options such as using brushes. Win2D provides all of these options and more, and makes it easy to use them when you want. All of the Draw[…] methods offer many overloads that can accept additional parameters such as CanvasTextFormat (font family, size, etc) and CanvasStrokeStyle (dashes, dots, endcaps, etc). Feel free to explore the API surface to learn more about these options.

Dynamically generate drawing parameters

  1. Now, let's add some variety by drawing a bunch of shapes and text with randomized colors.

    Add the following code to the top of your MainWindow class. This is helper functionality to generate random values that you will use when drawing:

    C#
    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);
    }
  2. Modify your canvas_Draw method to draw using these random parameters:

    C#
    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()));
    }

    Let's break down how DrawText has changed. "Hello, World!" remains the same as before. The x and y offset parameters have been replaced with a single System.Numerics.Vector2 which is generated by RndPosition. Finally, instead of using a predefined color, Color.FromArgb allows you to define a color using A, R, G and B values. A is alpha, or the opacity level; in this case you always want fully opaque (255).

    DrawCircle and DrawLine operate similarly to DrawText.

  3. Finally, wrap your drawing code in a for loop. You should end up with the following canvas_Draw code:

    C#
    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()));
    }
  4. Run the app again. You should see a whole bunch of text, lines and circles with random positions and sizes.

Apply an image effect to your content

  1. Image effects, also known as filter effects, are graphical transformations that are applied to pixel data. Saturation, hue rotation, and Gaussian blur are some common image effects. Image effects can be chained together, producing sophisticated visual appearance for minimal effort.

    You use image effects by providing a source image (the content you're starting with), creating an effect such as GaussianBlurEffect, setting properties such as BlurAmount, and then drawing the effect's output with DrawImage.

    To apply an image effect to your text and shapes, you need to first render that content into a CanvasCommandList. This object is usable as an input to your effect.

  2. Change your canvas_Draw method to use the following code:

    C#
    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()));
        }
    }

    Just like how you obtain a CanvasDrawingSession from CanvasDrawEventArgs which you can draw with, you can create a CanvasDrawingSession from a CanvasCommandList. The only difference is that when you draw to the command list's drawing session (clds), you are not directly rendering to the CanvasControl. Instead, the command list is an intermediate object that stores the results of rendering for later use.

    You may have noticed the using block that wraps the command list's drawing session. Drawing sessions implement IDisposable and must be disposed when you are done rendering (the using block does this). The CanvasDrawingSession that you obtain from CanvasDrawEventArgs automatically is closed for you, but you must dispose any drawing sessions that you explicitly created.

  3. Finally, define the GaussianBlurEffect by adding the following code to the end of the canvas_Draw method:

    C#
    GaussianBlurEffect blur = new GaussianBlurEffect();
    blur.Source = cl;
    blur.BlurAmount = 10.0f;
    args.DrawingSession.DrawImage(blur);

    This code creates a Gaussian blur, sets its source as the CanvasCommandList you just drew to, sets its blur radius to 10, and finally renders the output of the blur to the original drawing session (args.DrawingSession).

  4. Run the app again. You should see your lines, text and circles with a blurry appearance.