ilmago ilmago

Niner since 2012

I am Silvano Bonacina and am a developer in the Human Interaction Platform team within the Developer Experience group.


  • Bring pen and touch input to your Metro style apps with ink

    You can indeed use the inking API with C# and XAML, however be aware that the performant rendering of live Ink in XAML is still being investigated. You collect live ink by processing pointer events and calling the InkManager's ProcessPointer* APIs, but you must do the rendering yourself as the inking API does not provide the functionality for rendering. The (current) concern with live rendering is that the latency introduced by WPF's retained-mode graphics causes lagging between the input device and the rendering. The lagging is far more apparent with pen than it is with mouse, due to the proximity of the pen to the actual rendering on the screen.

    The InkManager doesn't need to be bound to any control, you just create it from code:

    var inkManager = new Windows.UI.Input.Inking.InkManager();

    Here's the example for offline rendering of stored ink on a XAML panel (eg. a canvas):

    public static class RenderingHelpers
        // Offline Bezier rendering.
        // Renders the ink saved within inkManager on panel.
        public static void RenderInk(Windows.UI.Xaml.Controls.Panel panel, Windows.UI.Input.Inking.InkManager inkManager)
            foreach (Windows.UI.Input.Inking.IInkStroke stroke in inkManager.GetStrokes())
                if (stroke.GetRenderingSegments().Count > 0)
        // Creates the data structure that renders the stroke.
        static Windows.UI.Xaml.Shapes.Path CreatePathForStroke(Windows.UI.Input.Inking.IInkStroke stroke)
            var figure = new Windows.UI.Xaml.Media.PathFigure();
            Windows.UI.Xaml.Shapes.Path path = null;
            // First segment is degenerate and corresponds to initial position
            var segments = stroke.GetRenderingSegments().GetEnumerator();
            if (segments.MoveNext())
                figure.StartPoint = segments.Current.Position;
                while (segments.MoveNext())
                    var bs = new Windows.UI.Xaml.Media.BezierSegment();
                    bs.Point1 = segments.Current.BezierControlPoint1;
                    bs.Point2 = segments.Current.BezierControlPoint2;
                    bs.Point3 = segments.Current.Position;
                var geometry = new Windows.UI.Xaml.Media.PathGeometry();
                path = new Windows.UI.Xaml.Shapes.Path();
                path.Data = geometry;
                path.Stroke = new Windows.UI.Xaml.Media.SolidColorBrush(int2color(stroke.DrawingAttributes.Color));
                path.StrokeThickness = stroke.DrawingAttributes.Size.Width;
            return path;
        static Windows.UI.Xaml.Media.Color int2Color(int iColor)
            byte alpha = (byte)  (0xff);
            byte red   = (byte)  (iColor & 0x0000ff);
            byte green = (byte) ((iColor & 0x00ff00) >> 8);
            byte blue  = (byte) ((iColor & 0xff0000) >> 16);
            return Windows.UI.Xaml.Media.ColorHelper.FromArgb(alpha, red, green, blue);