Pointer Input Events in Windows Store Apps Using XAML

This article describes the various input pointer events that can be helpful when designing Windows Store Apps using XAML.

In my previous article I showed two events of Pointer input; MouseHover and MouseExit. You can see that from here.

But now I will show another 4 types of pointer input events that Windows Store apps support; they are:

  • PointerPressed: It occurs when the pointer is pressed on the screen.
  • PointerMoved: It occurs when the pointer is moving around the screen.
  • PointerReleased: It occurs when the pointer button is released after being pressed.
  • PointerExisted: It works the same as PointerReleased but maybe in another condition too.
So, here I will create an application using these pointer events. 

Procedure to be followed.

Step 1

Create a Blank Windows Store App using C#.

Step 2

Here I create some XAML markup code for the UI design; it is:

<Page

    x:Class="drawingapp.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:local="using:drawingapp"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d">

 

    <Grid >

        <Grid.Background>

            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

                <GradientStop Color="Black"/>

                <GradientStop Color="#FFCD7070" Offset="1"/>

            </LinearGradientBrush>

        </Grid.Background>

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>      

        <Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30,30,0,0" Grid.Row="1">

            <StackPanel ManipulationMode="All">

                <Canvas x:Name="DrawingArea" Background="White" Height="500" Width="900"/>

                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,10">

                    <Button x:Name="Erase" Content="Erase" Margin="0,0,10,0"  Click="Erase_Click_1"/>

                    <Button x:Name="Draw" Content="Draw" Margin="0,0,10,0" Click="Draw_Click_1"/>

                    <Button x:Name="Reset" Content="Reset" Margin="0,0,10,0"  Click="Reset_Click_1"/>                  

                </StackPanel>               

            </StackPanel>

        </Grid>

    </Grid>

</Page>

Step 3

Here is the code of code-behind file.

Declare the 4 events of the input pointer at the initialization point. See:
 

DrawingArea.PointerPressed += new PointerEventHandler(DrawingArea_PointerPressed);

DrawingArea.PointerMoved += new PointerEventHandler(DrawingArea_PointerMoved);

DrawingArea.PointerReleased += new PointerEventHandler(DrawingArea_PointerReleased);

DrawingArea.PointerExited += new PointerEventHandler(DrawingArea_PointerReleased);

Code of PointerPressed Event:

void DrawingArea_PointerPressed(object sender, PointerRoutedEventArgs e)

{

    Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(DrawingArea);

    contacts[pt.PointerId] = pt.Position;

    e.Handled = true;

    ++ActiveContacts;

}

The above code gets the current pointer position.

Code of PointerRelease Event.

void DrawingArea_PointerReleased(object sender, PointerRoutedEventArgs e)

{

    uint ptrId = e.GetCurrentPoint(sender as FrameworkElement).PointerId;

    if (contacts.ContainsKey(ptrId))

    {

        contacts[ptrId] = null;

        contacts.Remove(ptrId);

        --ActiveContacts;

    }

   e.Handled = true;

}

Code of PointerMoved Event.

void DrawingArea_PointerMoved(object sender, PointerRoutedEventArgs e)

{

   if (i == 0)

    {

       Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(DrawingArea);

       uint ptrId = pt.PointerId;

       if (contacts.ContainsKey(ptrId) && contacts[ptrId].HasValue)

       {

          Point currentContact = pt.Position;

          Point previousContact = contacts[ptrId].Value;

          if (Distance(currentContact, previousContact) > 4)

          {

             Line l = new Line()

             {

                 X1 = previousContact.X,

                 Y1 = previousContact.Y,

                 X2 = currentContact.X,

                 Y2 = currentContact.Y,

                 StrokeThickness = THICKNESS,

                 Stroke = new SolidColorBrush(Colors.Green),

                 StrokeEndLineCap = PenLineCap.Round

             };

          contacts[ptrId] = currentContact;

          ((System.Collections.Generic.IList<UIElement>)DrawingArea.Children).Add(l);

         }

       }

    }

    else

    {

       Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(DrawingArea);

       uint ptrId = pt.PointerId;

       if (contacts.ContainsKey(ptrId) && contacts[ptrId].HasValue)

       {

           Point currentContact = pt.Position;

           Point previousContact = contacts[ptrId].Value;

           if (Distance(currentContact, previousContact) > 4)

           {

              Line l = new Line()

             {

               X1 = previousContact.X,

               Y1 = previousContact.Y,

               X2 = currentContact.X,

               Y2 = currentContact.Y,

               StrokeThickness = THICKNESS + 12,

               Stroke = new SolidColorBrush(Colors.White),

               StrokeEndLineCap = PenLineCap.Round

              };

              contacts[ptrId] = currentContact;

             ((System.Collections.Generic.IList<UIElement>)DrawingArea.Children).Add(l);

           }

        }

    }

    e.Handled = true;

}

Step 4

The complete code of the MainPage.cs file:

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using Windows.Foundation;

using Windows.Foundation.Collections;

using Windows.UI;

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.Navigation;

using Windows.UI.Xaml.Shapes;

 

namespace drawingapp

{

    public sealed partial class MainPage : Page

    {

        const uint CONTACTS = 10;

        const double THICKNESS = 5;

        uint ActiveContacts;

        Dictionary<uint, Point?> contacts;

 

        public MainPage()

        {

            this.InitializeComponent();

            ActiveContacts = 0;

            contacts = new Dictionary<uint, Point?>((int)CONTACTS);

            DrawingArea.PointerPressed += new PointerEventHandler(DrawingArea_PointerPressed);

            DrawingArea.PointerMoved += new PointerEventHandler(DrawingArea_PointerMoved);

            DrawingArea.PointerReleased += new PointerEventHandler(DrawingArea_PointerReleased);

            DrawingArea.PointerExited += new PointerEventHandler(DrawingArea_PointerReleased);

        }

        protected override void OnNavigatedTo(NavigationEventArgs e)

        {

        }

        void DrawingArea_PointerReleased(object sender, PointerRoutedEventArgs e)

        {

            uint ptrId = e.GetCurrentPoint(sender as FrameworkElement).PointerId;

            if (contacts.ContainsKey(ptrId))

            {

                contacts[ptrId] = null;

                contacts.Remove(ptrId);

                --ActiveContacts;

            }

            e.Handled = true;

        }

        void DrawingArea_PointerMoved(object sender, PointerRoutedEventArgs e)

        {

            if (i == 0)

            {

                Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(DrawingArea);

                uint ptrId = pt.PointerId;

                if (contacts.ContainsKey(ptrId) && contacts[ptrId].HasValue)

                {

                    Point currentContact = pt.Position;

                    Point previousContact = contacts[ptrId].Value;

                    if (Distance(currentContact, previousContact) > 4)

                    {

                        Line l = new Line()

                        {

                            X1 = previousContact.X,

                            Y1 = previousContact.Y,

                            X2 = currentContact.X,

                            Y2 = currentContact.Y,

                            StrokeThickness = THICKNESS,

                            Stroke = new SolidColorBrush(Colors.Green),

                            StrokeEndLineCap = PenLineCap.Round

                        };

                        contacts[ptrId] = currentContact;

                        ((System.Collections.Generic.IList<UIElement>)DrawingArea.Children).Add(l);

                    }

                }

            }

            else

            {

                Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(DrawingArea);

                uint ptrId = pt.PointerId;

                if (contacts.ContainsKey(ptrId) && contacts[ptrId].HasValue)

                {

                    Point currentContact = pt.Position;

                    Point previousContact = contacts[ptrId].Value;

                    if (Distance(currentContact, previousContact) > 4)

                    {

                        Line l = new Line()

                        {

                            X1 = previousContact.X,

                            Y1 = previousContact.Y,

                            X2 = currentContact.X,

                            Y2 = currentContact.Y,

                            StrokeThickness = THICKNESS + 12,

                            Stroke = new SolidColorBrush(Colors.White),

                            StrokeEndLineCap = PenLineCap.Round

                        };

                        contacts[ptrId] = currentContact;

                        ((System.Collections.Generic.IList<UIElement>)DrawingArea.Children).Add(l);

                    }

                }

            }

            e.Handled = true;

        }

        private double Distance(Point currentContact, Point previousContact)

        {

            return Math.Sqrt(Math.Pow(currentContact.X - previousContact.X, 2) + Math.Pow(currentContact.Y - previousContact.Y, 2));

        }

        void DrawingArea_PointerPressed(object sender, PointerRoutedEventArgs e)

        {

            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(DrawingArea);

            contacts[pt.PointerId] = pt.Position;

            e.Handled = true;

            ++ActiveContacts;

        }

        int i = 0;

        public void AllClear()

        {

            ((System.Collections.Generic.IList<UIElement>)DrawingArea.Children).Clear();

            ActiveContacts = 0;

            if (contacts != null)

            {

                contacts.Clear();

            }

        }

        private void Draw_Click_1(object sender, RoutedEventArgs e)

        {

            i = 0;

        }

        private void Erase_Click_1(object sender, RoutedEventArgs e)

        {

            i = 1;

        }

        private void Reset_Click_1(object sender, RoutedEventArgs e)

        {

            AllClear();

        }

    }

}


Step 5

Output

Now, our Windows Store App is ready to run. Press F5 to run it.

You will see that there are 3 buttons and one white canvas in which you can write or paint.

Pointer-input-events-in-Windows-Store-Apps.jpg

Select the Draw button to draw onto the given canvas.

pointer-moved-event-windows-store-apps.jpg

Select the Erase button to erase the content of the canvas.

pointer-released-event-in-windows-store-apps.jpg

The Reset button is used to remove all the content of the canvas at once.

Next Recommended Readings