If you’re building a Windows/Phone app in C#/C++ and want to draw in 2D then your current options are a bit limited. You can go via the high level approach of using Canvas from the XAML bits but that’s a way of doing “retained mode” drawing whereas there isn’t really an API that’s surfaced to you for “immediate mode” drawing such as you’d see in the desktop .NET framework via something like the functionality you get from something like System.Drawing.
That’s not to say that you can’t do it. You can look at WriteableBitmap and its various extensions that people have built on it or you can interop between DirectX and XAML as per;
DirectX and XAML Interop
and as per the improvements made in 8.1;
What’s New for XAML and DirectX Interop in Windows 8.1
but then on the flip side of that interop you’re coding against the Direct2D APIs which aren’t surfaced into .NET and so you’d need to find some way of calling those which might involve something like SharpDX to get you access to those APIs which don’t perhaps feel entirely “natural” to the C# developer who’s building a Windows/Phone app.
It’s a question of finding the right tools for the job and not having to jump through hoops and so I was quite intrigued to see the announcement around a new WinRT API for 2D drawing which surfaces itself to both C# and C++.
Introducing Win2D
and the project on github;
https://github.com/Microsoft/Win2D
where it is currently being built – i.e. this is a “work in progress” rather than something that’s something that’s been “shipped” at the time of writing.
Getting those Bits
In terms of getting the bits, this introduction is what you need;
introduction
which essentially involves cloning down the bits from github and running the build.cmd file found in the top level Win2D folder from a “Developer Command Prompt for VS 2013” command window (you do need VS 2013 Update 2).
Make sure that you have nuget.exe on your PATH and what will pop out in the bin folder are two NuGet packages for the bits with/without debug.
Once you’ve got those NuGet packages you can put them in a local repository (which you can manage via the VS dialog) – I have one present on my machine in the folder d:\packageSource as per the dialog below;

and then you’re ready to start by adding Win2D to a Windows/Phone 8.1 project from that local repository;

while remembering that because you just brought in a bunch of native code you need to change your build configuration to something that’s processor specific like x86 and you’re then ready to start with the CanvasControl which is usable from Windows/Phone XAML.
The rest of this post are just some notes I played while trying to explore the API – I spent around an hour with it and found it to be pretty discoverable and intuitive in so far as I’ve tried it out.
Drawing Something, Anything 
My first “Hello World” then was kept deliberately small. I simply had a blank Windows 8.1 XAML/C# project and I removed MainPage.xaml and MainPage.xaml.cs and then I hacked App.xaml.cs down to;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
if (!this.launched)
{
// Wonder how this will stretch?
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.Yellow);
args.DrawingSession.DrawText("Hello World",
new Vector2() { X = 96, Y = 96 }, Colors.Red);
}
bool launched;
}
}
Sure, no application lifecycle in there, no code to handle launching from a secondary tile etc. etc. but who needs any of that inside of “Hello World”?
As you’d expect, this produces some red text on a yellow background and the CanvasControl seemed to stretch itself out nicely regardless of what I did with the app’s window;

Trying to Draw Lots and Lots of Things
That led me to wonder how often my Draw method was being called so I changed the function to be;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.drawCount = 0;
}
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
if (!this.launched)
{
// Wonder how this will stretch?
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (this.drawCount == 0)
{
args.DrawingSession.Clear(Colors.Yellow);
}
this.drawCount++;
args.DrawingSession.DrawText(this.drawCount.ToString(),
new Vector2() { X = 96, Y = 96 }, Colors.Red);
}
int drawCount;
bool launched;
}
}
which I found to be really interesting in that it reminded me that I was playing with an immediate mode drawing API here! So, first-off this code displays;

but if I then resize the window down to half the screen then I get;

which made me laugh when I first did it because I had more of an expectation that the Draw method would be called on a per-frame basics which it isn’t (i.e. which is 100% what I should have expected).
Naturally, the CanvasControl has been invalidated because of the resize and so has redrawn itself but my code doesn’t clear the background to yellow on the second iteration so the yellow is gone but the draw count has been driven to 2 because of the invalidation.
What if I wanted to draw on some kind of loop to match my misguided expectation? There’s an Invalidate method on that CanvasControl and my first thought was to see whether I would break things by attempting to run a drawing loop on a non-UI thread as per below;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using System.Threading;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.drawCount = 0;
}
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
if (!this.launched)
{
// Wonder how this will stretch?
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
Window.Current.Content = control;
this.launched = true;
this.nonDispatcherTimer = new Timer(
_ =>
{
control.Invalidate();
},
null,
0,
10);
}
Window.Current.Activate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.Yellow);
this.drawCount++;
args.DrawingSession.DrawText(this.drawCount.ToString(),
100, 100, Colors.Red);
}
Timer nonDispatcherTimer;
int drawCount;
bool launched;
}
}
but, naturally, that hit me with the not unexpected;

Naturally, I could use a DispatcherTimer here in order to run a timer-based drawing loop on the dispatcher/UI thread but, rather than that, I simply switched to calling Invalidate directly from the Draw handler, wondering if that would cause some kind of recursive mayhem but it seemed to work fine;
namespace App256
{
using Microsoft.Graphics.Canvas;
using System;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.lastTicks = 0;
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.launched)
{
this.DebugSettings.EnableFrameRateCounter = true;
// Wonder how this will stretch?
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
args.DrawingSession.Clear(Colors.Yellow);
args.DrawingSession.DrawText(
((DateTime.Now.Ticks - this.lastTicks) / 10000).ToString(),
100,
100,
Colors.Red);
this.lastTicks = DateTime.Now.Ticks;
sender.Invalidate();
}
long lastTicks;
bool launched;
}
}
and seemed to tick away at about 16ms between frames giving a framerate of around 60fps. I wondered if I could draw a few things…there are methods for circles, lines, ellipses, rectangles, rounded rectangles and similar methods for filling in shapes so I tried;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using System;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.random = new Random();
this.circleCenter = new Vector2();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.launched)
{
this.DebugSettings.EnableFrameRateCounter = true;
// Wonder how this will stretch?
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
using (CanvasDrawingSession session = args.DrawingSession)
{
session.Clear(Colors.Yellow);
double width = sender.ActualWidth;
double height = sender.ActualHeight;
for (int i = 0; i < 100; i++)
{
float radius = random.Next(MINRADIUS, MAXRADIUS);
this.circleCenter.X = random.Next((int)radius, (int)(width - radius));
this.circleCenter.Y = random.Next((int)radius, (int)(height - radius));
session.DrawCircle(this.circleCenter, radius, Colors.Green);
}
}
sender.Invalidate();
}
readonly int MINRADIUS = 5;
readonly int MAXRADIUS = 20;
Vector2 circleCenter;
Random random;
bool launched;
}
}
and that seemed to tick away quite happily drawing 100 circles per call (you might also notice that I’d started to Dispose of the DrawingSession object at this point as the docs suggest);

and that also worked pretty well for me in drawing higher numbers of circles – e.g. 1000 circles at around 50fps and 5000 circles at around 20fps and by 10,000 circles it was around 6fps but I made no attempt to improve any of the code here and see if I could speed up my initial approach, I just wanted to play around with it and see how it worked out.
Integrating With Other XAML Content
I also wondered how this CanvasControl content integrated with other content and so I quickly placed a MediaElement behind the CanvasControl above in my code, set that MediaElement playing a video from the web and made sure that the background on the CanvasControl was transparent. That seemed to work out fine and here’s a screen shot of those same circles being drawn onto a CanvasControl while underneath there’s a MediaElement streaming the “Big Buck Bunny” movie. As you’d expect, in order to make that work I had to remove the code I have above which clears the background to Yellow each time the code draws otherwise you end up with an HD video obscured behind a solid wall of Yellow;

Filling with Brushes
In looking at some of those Draw/Fill methods like CanvasDrawingSession.FillCircle I noticed that there were overloads that took an ICanvasBrush of which there look to be solid, gradient, radial, image variants. So, it looks like I can write code such as;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using System;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.launched)
{
this.DebugSettings.EnableFrameRateCounter = true;
// Wonder how this will stretch?
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
using (CanvasDrawingSession session = args.DrawingSession)
{
session.FillCircle(
new Vector2() { X = (float)(sender.ActualWidth / 2), Y = (float)(sender.ActualHeight / 2) },
200.0f,
new CanvasSolidColorBrush(session.Device, Colors.Blue) { Opacity = 1.0f });
session.FillCircle(
new Vector2() { X = (float)(sender.ActualWidth / 2), Y = (float)(sender.ActualHeight / 2) },
100.0f,
new CanvasSolidColorBrush(session.Device, Colors.Red) { Opacity = 0.5f });
}
}
bool launched;
}
}
and get a nice purple target in the centre of the screen;

or I could use some kind of gradient from my OnDraw code;
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
using (CanvasDrawingSession session = args.DrawingSession)
{
Vector2 centre = new Vector2()
{
X = (float)(sender.ActualWidth / 2),
Y = (float)(sender.ActualHeight / 2)
};
var radius = 100.0f;
session.FillCircle(
centre,
radius,
new CanvasRadialGradientBrush(
session.Device,
new CanvasGradientStop[] {
new CanvasGradientStop() { Color=Colors.Red, Position = 0.0f },
new CanvasGradientStop() { Color=Colors.Blue, Position = 0.25f},
new CanvasGradientStop() { Color=Colors.Yellow, Position = 1.0f },
},
CanvasEdgeBehavior.Clamp,
CanvasAlphaBehavior.Premultiplied)
{
RadiusX = radius,
RadiusY = radius,
Center = centre
});
}
}
giving me a nice;

Drawing Images
Again, looking at those overloaded Draw/Fill methods quite naturally led me to think about filling these shapes with images and I wound back a little and looked at the various overloads of CanvasDrawingSession.DrawImage which in turn led to trying to work out what an ICanvasImage might be with the specific instance seeming to be the CanvasBitmap class.
This led me to the CreateResources event on the CanvasControl which I can use (as per the example in the docs) to create items that I’m going to need by the time that I reach my drawing code and, in my case, I’m using that CreatResources event to download an image I found on the Microsoft home page on the web;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.launched)
{
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
control.CreateResources += OnCreateResources;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
async void OnCreateResources(CanvasControl sender, object args)
{
this.image = await CanvasBitmap.LoadAsync(sender.Device,
new Uri("http://c.s-microsoft.com/en-gb/CMSImages/MSNPrime_HikerBG_0826_1600x540_EN_US.jpg?version=23bd323a-4539-c38f-49ba-9cd4b3474fb4"));
this.imageLoaded = true;
sender.Invalidate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (this.imageLoaded)
{
using (var session = args.DrawingSession)
{
float width = (float)sender.ActualWidth / 3.0f;
// assuming this fits...
float height = (float)(width / this.image.SizeInPixels.Width * this.image.SizeInPixels.Height);
session.DrawImage(
this.image,
new Rect((sender.ActualWidth - width) / 2, (sender.ActualHeight - height) / 2, width, height),
new Rect(0, 0, this.image.SizeInPixels.Width, this.image.SizeInPixels.Height));
}
}
}
bool imageLoaded;
CanvasBitmap image;
bool launched;
}
}
and that code then attempts to position the image in the middle of the screen scaled such that it is 1/3rd of the width available with the height appropriately scaled. I’ll return to the “attempts to” part of that statement in a moment as I’m not at all sure I have it right just yet;

and I can then do something like take the bottom left 96×96 pixels of the image above and use it as a “tiled brush” in order to fill some other area like a circle as per below;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Numerics;
using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.launched)
{
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
control.CreateResources += OnCreateResources;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
async void OnCreateResources(CanvasControl sender, object args)
{
this.image = await CanvasBitmap.LoadAsync(sender.Device,
new Uri("http://c.s-microsoft.com/en-gb/CMSImages/MSNPrime_HikerBG_0826_1600x540_EN_US.jpg?version=23bd323a-4539-c38f-49ba-9cd4b3474fb4"));
this.imageBrush = new CanvasImageBrush(sender.Device,
this.image)
{
ExtendX = CanvasEdgeBehavior.Wrap,
ExtendY = CanvasEdgeBehavior.Wrap,
SourceRectangle = new Rect(
0, this.image.SizeInPixels.Height - 96, 96, 96)
};
this.imageLoaded = true;
sender.Invalidate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (this.imageLoaded)
{
using (var session = args.DrawingSession)
{
session.FillCircle(
new Vector2() { X = (float)sender.ActualWidth / 2, Y = (float)sender.ActualHeight / 2 },
300.0f,
this.imageBrush);
}
}
}
bool imageLoaded;
CanvasBitmap image;
CanvasImageBrush imageBrush;
bool launched;
}
}
producing a nice, grass-like effect
Talking of effects…

Applying Effects
ICanvasImage proves to be more than being just about images in that there are a bunch of effects as listed in the docs and those effects implement ICanvasImage so they are effectively “images” and can be used wherever I can use an image. Very cool 
Those effects are also IEffect which I probably haven’t fully understood at the time of writing but an effect just seems to be something with an id, some inputs and some properties which is simple enough. Those inputs need to implement IEffectInput which seems to be just a marker interface at the moment. The effects look to map on fairly directly to Direct2D effects and the documentation makes that mapping for you in case you’re coming from that world and want to compare/contrast.
Trying this out, I took the code I’d just written and modified it a little to try and apply an effect like this ScaleEffect below;
namespace App256
{
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.Numerics;
using System;
using Windows.ApplicationModel.Activation;
using Windows.Graphics.Display;
using Windows.UI.Xaml;
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
if (!this.launched)
{
CanvasControl control = new CanvasControl();
control.Draw += OnDraw;
control.CreateResources += OnCreateResources;
Window.Current.Content = control;
this.launched = true;
}
Window.Current.Activate();
}
async void OnCreateResources(CanvasControl sender, object args)
{
this.image = await CanvasBitmap.LoadAsync(sender.Device,
new Uri("http://c.s-microsoft.com/en-gb/CMSImages/MSNPrime_HikerBG_0826_1600x540_EN_US.jpg?version=23bd323a-4539-c38f-49ba-9cd4b3474fb4"));
this.imageLoaded = true;
sender.Invalidate();
}
void OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (this.imageLoaded)
{
using (var session = args.DrawingSession)
{
// I can ask for Pixels here but sender.ActualWidth and ActualHeight
// are still going to come back as logical values. That is - on my
// 12" 1920x1080 display with 140% scaling they come back as
// 1366x768 which I then struggle to make work with the other bits
// here. Hence, I'm turning into pixel values myself which is
// probably wrong but I notice that this.image.Size and
// this.image.SizeInPixels gives me the same result either way.
session.Units = CanvasUnits.Pixels;
// TBD: I'm not at all sure about this but if I don't use it then I get the wrong results
// on my higher DPI display and decent results on a lower one.
double displayScaling = DisplayInformation.GetForCurrentView().LogicalDpi / 96.0;
double pixelWidth = sender.ActualWidth * displayScaling;
double pixelHeight = sender.ActualHeight * displayScaling;
double width = pixelWidth / 2;
double height = (this.image.Size.Height / this.image.Size.Width) * width;
ScaleEffect scale = new ScaleEffect()
{
Source = this.image,
Scale = new Vector2()
{
X = (float)(width / this.image.Size.Width),
Y = (float)(height / this.image.Size.Height)
}
};
session.DrawImage(
scale,
(float)((pixelWidth - width) / 2),
(float)((pixelHeight - height) / 2));
}
}
}
bool imageLoaded;
CanvasBitmap image;
bool launched;
}
}
I may have gone off the rails with that code and also with some of the earlier code that I wrote which tried to size something so as to occupy a particular size/area of the screen.
I saw that because while trying to get this code to “work” I spent a lot of time looking at CanvasDrawingSession.Units and also the difference between CanvasBitmap.Size and CanvasBitmap.SizeInPixels which, on my machine, seemed to be returning the same value for the image I was looking at whereas the docs say that one of these is a size in pixels and the other is a size in device independent units.
What I’m trying to do in the code above is to scale the image such that it’s width is half the width of the available width and then proportionately scale the height and, finally, position the image in the middle of the display area as below;

What I seemed to bang up against was that the image is sized in pixels but the CanvasControl size reports itself in device independent pixels via the ActualWidth/Height properties (which is what I’d expect for anything from the XAML world) and so my attempt to mix/match these different co-ordinate systems didn’t work out unless I took account of the display scaling as I try and do in the code above but it wasn’t where I started from and perhaps there’s a better, more intuitive way of doing this.
Getting back to effects, I could change that OnDraw code to add more effects such as;
ScaleEffect scale = new ScaleEffect()
{
Source = this.image,
Scale = new Vector2()
{
X = (float)(width / this.image.Size.Width),
Y = (float)(height / this.image.Size.Height)
}
};
GaussianBlurEffect blur = new GaussianBlurEffect()
{
Source = scale,
BlurAmount = 5.0f
};
SaturationEffect sat = new SaturationEffect()
{
Saturation = 0.5f,
Source = blur
};
session.DrawImage(
sat,
(float)((pixelWidth - width) / 2),
(float)((pixelHeight - height) / 2));
and they all start to chain together quite nicely;

To Be Continued…
For the moment, that’s what I’ve played with in this API. I have a couple of ideas around uses for it though so I’ll blog a few follow-on posts as/when I get some of those written.
For now, if you have scenarios where you need to do drawing or image manipulation you might want to take a look at what this API gives you as a new piece for your toolkit when it comes to Windows/Phone apps.