UK Future Decoded Event Video: Stuart Lodge on Visual Studio and Xamarin

Microsoft UK recently ran the UK Future Decoded Event where I was the owner of a half-day track of sessions on Visual Studio for Cross Platform Applications. I described that track as;

There’s a tension between an app developer who wants to get the most from their investment in skills and tools and a device/platform vendor who wants to make sure that apps are really shiny on their devices.

What’s a dev to do? Build native for iOS/Android/Windows and take the hit on multiple code-bases? Go lowest, common denominator and build hybrid? Or…is there another way? Join us for an afternoon of getting bang up to date on how Visual Studio works with Xamarin and Cordova to get your code across as many devices as possible without compromising the user or developer experience.

The first session of the day was Stuart Lodge of Cirrious who’s also the creator of the MvvmCross framework for cross platform apps.

Stuart delivered a great session entitled “Visual Studio & Xamarin: Native C# Apps on iOS & Android devices” and the video is now available for you to watch below;

Enjoy!

Future Decoded Event – Cross Platform Apps with Visual Studio, Excel, London, 12th November (free)

I wanted to publicise a company-wide event that Microsoft is running at Excel, London in the week of the 10th November and, specifically, the developer part of the event which happens on the 12th November.

I own a half-day track on that developer day which I have themed around “Visual Studio for Cross Platform Apps” but that’s just one of many technical tracks across big data, DevOps, Enterprise Mobility, Cloud, IoT and more – it’s a big event with a big agenda and, importantly, it’s all free!

All the details and the registration link are behind the picture below where I’ve tried to highlight the speakers you’d see if you came along to my section of the day but take a look at the full agenda – there’s a tonne going on;

Picture1

Visual Studio for Cross Platform Apps Track

We have an afternoon of sessions across;

  • Visual Studio and Xamarin for Cross Platform Apps
  • Visual Studio and Universal Apps for Windows/Phone
  • Visual Studio and Cordova for Cross Platform Apps

and I’m very lucky to be joined by the creator of MvvmCross and all round top chap Stuart Lodge to talk about Visual Studio and Xamarin;

“Let's take a tour of the tools offered by Xamarin within Visual Studio. We'll start from ‘File -> New Project –> Android’ and ‘File -> New Project –> iPhone’ and we'll explore what it takes to create an app – to build its business logic, to create a rich ui, and to talk to services like GeoLocation. This is a practical session – working with the Xamarin tools and looking at the developer workflow they enable. What's it feel like to code, design, debug, iterate and ship to Android and iOS from Visual Studio?

Xamarin's mission is to delight developers – can they delight you?”

image

and by my colleague Martin Beeby to talk about Visual Studio and Cordova – note that the agenda has a bug or two here which I’ve marked below with nice red crosses while the website gets fixed;

“If someone asked you to build an iOS or Android app, could you do it? What if you could do it all in JavaScript? In this session, we'll show how Apache Cordova opens the world of mobile app development to web developers. You'll learn what kind of apps are best-suited for the hybrid architecture and when to make the switch from web app to mobile app. You'll also walk away with a list of tools, tips and tricks you can use to make your first attempt at mobile app development a success.

image

and then I will be talking a little around the ideas of Universal Apps for Windows/Phone from the point of view of a C# developer with this talk;

“In terms of apps, Windows/Phone have been a case of "two platforms separated by a common vendor".

That changed with the 8.1 release of the platforms which have been unified around the underlying WinRT APIs such that it's possible to build a significant portion of an app across Windows/Phone from common code without losing the ability to customise the app for a particular class of device.

In this session we'll look at what this means for C# developers in Visual Studio by looking at the options that you have for building portable C# code that can run on both Windows and Phone and some of the considerations that you need to make when building out application code that you want to have run on both.

We'll work mostly in Visual Studio rather than PowerPoint and our focus will be with C#/.NET but we will also talk briefly around other options for producing "universal" Windows/Phone apps.”

image

I like that I included the “currently work for Microsoft” in that little bio of myself – good to recognise that nothing’s certain in this world Smile

I hope to see you there!

Win2D – WinRT API for 2D Graphics

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;

image

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

image

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 Smile

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;

image

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;

image

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

image

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;

image

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);

image

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;

image

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;

image

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;

image

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;

image

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 Smile Talking of effects…

image

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 Smile

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;

image

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;

image

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.