xamlcanvaswindows-phone-8.1writablebitmap

Signature capture in Windows Phone 8.1


I'm surprised that I'm unable to find any solution for capturing signature in Windows Phone 8.1. So far I found only one in StackOverflow here... but it complains that WriteableBitmap.DrawLine method isn't available.

Code from the above link:

using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

namespace ProofOfConcept.App.Controls
{
    public class SignatureCaptureControl : Canvas
    {
        private WriteableBitmap _writeableBitmap;

        private Point _currentPoint;
        private Point _oldPoint;

        public SignatureCaptureControl()
        {
            _writeableBitmap = new WriteableBitmap(300, 130);
            PointerPressed += SignatureCaptureControl_PointerPressed;
            PointerMoved += SignatureCaptureControl_PointerMoved;
        }

        private void SignatureCaptureControl_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            _currentPoint = e.GetCurrentPoint(this).Position;
            _oldPoint = _currentPoint;
        }

        void SignatureCaptureControl_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            _currentPoint = e.GetCurrentPoint(this).Position;
            _writeableBitmap.DrawLine((int)_currentPoint.X, (int)_currentPoint.Y, (int)_oldPoint.X, (int)_oldPoint.Y, PenColor);
            this.InvalidateArrange();
            _oldPoint = _currentPoint;
        }

        public void ClearSignature()
        {
            _writeableBitmap.Clear();
        }    
    }    
}

Solution

  • Finally I found a sample code that does exactly what I was looking for. It does let the user scribble their signature or whatever on the canvas, I'm yet to figure out how to save the image and upload it to a webservice. I'll get to that later. But here is the code to create a drawing pad.

    Link to the website where I found the code.

    I made it as a UserControl.

    This is how I used the UserControl:

    <Grid x:Name="inkPanel">
        <Controls:SignatureCaptureControl/>
    </Grid>
    

    UserControl Xaml:

    <UserControl
        x:Class="MyApp.Controls.SignatureCaptureControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MyApp.Controls"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="170"></RowDefinition>
            <RowDefinition Height="60"></RowDefinition>
            <RowDefinition Height="50"></RowDefinition>
        </Grid.RowDefinitions>
        <Canvas x:Name="inkCanvas" Grid.Row="0">
            <Rectangle x:Name="rect" VerticalAlignment="Top" Height="150" Width="360" Fill="#FFF4F4F5" Stroke="Black" />
        </Canvas>
        <PasswordBox x:Name="txtPin" Grid.Row="1" Width="360" PlaceholderText="Enter Pin">
        </PasswordBox>
        <StackPanel Orientation="Horizontal" Grid.Row="2" Margin="0,10,0,0" HorizontalAlignment="Center">
            <Button Name="btnAccept" Content="Accept" Click="btnAccept_Click"></Button>
            <Button Name="btnClear" Content="Clear" Click="btnClear_Click"></Button>
        </StackPanel>
    </Grid>
    </UserControl>
    

    Code Behind:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Xaml.Navigation;
    using Windows.UI;
    
    // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
    
    namespace MyApp.Controls
    {
        public sealed partial class SignatureCaptureControl : UserControl
        {
            Windows.UI.Xaml.Shapes.Path _Current;
    
            public SignatureCaptureControl()
            {
                this.InitializeComponent();
                inkCanvas.PointerPressed += inkCanvas_PointerPressed;
                inkCanvas.PointerMoved += inkCanvas_PointerMoved;
                inkCanvas.PointerReleased += inkCanvas_PointerReleased;
                inkCanvas.PointerExited += inkCanvas_PointerReleased;
            }
    
            void inkCanvas_PointerReleased(object sender, PointerRoutedEventArgs e)
            {
                _Current = null;
            }
    
            void inkCanvas_PointerMoved(object sender, PointerRoutedEventArgs e)
            {
                var pointer = e.GetCurrentPoint(inkCanvas);
                if (!pointer.Properties.IsLeftButtonPressed || _Current == null)
                    return;
                var segments = (_Current.Data as PathGeometry).Figures.First().Segments.First() as PolyLineSegment;
                segments.Points.Add(pointer.Position);
            }
    
            void inkCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)
            {
                var pointer = e.GetCurrentPoint(inkCanvas);
                if (!pointer.Properties.IsLeftButtonPressed)
                    return;
    
                _Current = new Windows.UI.Xaml.Shapes.Path
                {
                    Data = new PathGeometry
                    {
                        Figures = { new PathFigure { StartPoint = pointer.Position, Segments = { new PolyLineSegment() } } }
                    },
                    Stroke = new SolidColorBrush(Colors.Black),
                    StrokeThickness = 4d,
                };
    
                inkCanvas.Children.Add(_Current);
            }
    
            private void btnClear_Click(object sender, RoutedEventArgs e)
            {
                inkCanvas.Children.Clear();
                inkCanvas.Children.Add(rect);
                txtPin.Password = "";
            }
    
            private void btnAccept_Click(object sender, RoutedEventArgs e)
            {
    
            }
        }
    }