User Tools

Site Tools


notes:uwp:input

Handling input in UWP

Types of user input in UWP:

  • touch
  • mouse
  • pen / stylus
  • keyboard

User input events can be grouped into three categories:

  • pointers - the low-level raw events
  • gestures - higher-level events calculated from the pointer events such as press and hold
  • manipulations - the highest-level events for complex gestures such as swipe, rotate, and pinch to zoom

In UWP the UIElement class is a base class for most of the objects that have visual appearance and that can process user input. This is a list of events defined by UIElement:

  • Input from touch, the mouse, and the pen:
    • PointerCanceled
    • PointerCaptureLost
    • PointerEntered
    • PointerExited
    • PointerMoved
    • PointerPressed
    • PointerReleased
    • PointerWheelChanged
  • Input from multiple fingers:
    • ManipulationCompleted
    • ManipulationDelta
    • ManipulationInertiaStarting
    • ManipulationStarted
    • ManipulationStarting
  • Keyboard input:
    • KeyDown
    • KeyUp
  • Higher level events:
    • Tapped - a mouse click, a tap with a pen, or a tap with a finger
    • DoubleTapped
    • RightTapped - a mouse right-button click or holding a finger down for a moment and then lifting (this gesture also generates Holding events)
    • Holding
  • Signalling when an element is the target of keyboard input:
    • GotFocus
    • LostFocus
  • Drap-and-drop events:
    • DragEnter
    • DragOver
    • DragLeave
    • Drop

The pointer events abstract touch, mouse, and pen input. They are:

  • low-level raw events
  • routed events i.e. they bubble up the visual tree
  • exposed by UIElement

Pointer events:

  • PointerPressed
  • PointerMoved
  • PointerReleased - raised when a previously pressed pointer releases contact while within the UIElement; note that PointerCanceled or PointerCaptureLost can be invoked instead of this event
  • PointerEntered
  • PointerExited - raised when a pointer leaves a UIElement's bounds, but only if the pointer was initially within this element's bounds
  • PointerCanceled - raised when the pointer that was previously in contact with the UIElement is lost due to an abnormal reason
  • PointerCaptureLost - raised when the pointer is lost from the UIElement while the user is carrying out an action
  • PointerWheelChanged

Properties and methods of the pointer event argument (PointerRoutedEventArgs):

  • GetCurrentPoint - returns the PointerPoint relative to the window or to a specified UIElement
  • Pointer - the pointer that raised the event
  • GetIntermediatePoints - a collection of accumulated PointerPoint objects (used with high-resolution input such as pen or touch digitizers)
  • Handled - used to stop bubbling
  • KeyModifiers

The pointer abstraction involves the following classes:

  • Windows.Devices.Input.PointerDevice - The physical device: touch digitizer, mouse, pen digitizer.
    • Hardware details such as MaxContacts and PointerDeviceType.
    • The PointerDevice.GetPointerDevices method returns a list of all the PointerDevices attached to the system
  • Windows.UI.Xaml.Input.Pointer - A single, unique input contact: a finger for the touch digitizer, the mouse pointer for the mouse, a pen for the pen digitizer.
    • PointerId uniquely identifies an input contact
  • Windows.UI.Input.PointerPoint - The input data from each pointer.
    • Position represents adjusted client coordinates of the pointer
    • IsInContact indicates if the pointer is touching the screen
    • Properties is an instance of the PointerPointProperties containing extra information about the input
    • The PointerPoint.GetCurrentPoint method returns the current PointerPoint for a specific pointer ID
    • The PointerPoint.GetIntermediatePoints method returns a collection of PointerPoints for a Pointer as the input device moves around the screen
  • Windows.UI.Input.PointerPointProperties - Extended information about each point.
    • ContactRect represents adjusted bounding rectangle of the contact area in client window coordinates
    • IsInRange indicates whether the pointer device is within close proximity to a sensor in the device or a digitizer
    • IsPrimary indicates whether the input is from the primary pointer - the first one that made contact

Instead of low-level pointer events it is better to use gesture and manipulation events for consistent experience across all applications.

Example: Draw on Canvas by handling its PointerPressed, PointerMoved, and PointerReleased events:

<Page
    x:Class="WBS.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="0.1*" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock Text="Drawing on a Canvas by handling its PointerPressed, PointerMoved, 
                         and PointerReleased events." 
                   Foreground="Black" FontSize="25" Margin="20" />
        <Canvas x:Name="Canvas1" Grid.Row="1" Background="Beige" 
                PointerPressed="Canvas1_PointerPressed" 
                PointerMoved="Canvas1_PointerMoved" 
                PointerReleased="Canvas1_PointerReleased" />
    </Grid>
</Page>
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
 
namespace WBS
{
    public sealed partial class MainPage : Page
    {
        private bool isDrawing = false;
 
        public MainPage4()
        {
            this.InitializeComponent();
        }
 
        private void Canvas1_PointerPressed(object sender, PointerRoutedEventArgs args)
        {
            PointerPoint point = args.GetCurrentPoint(Canvas1);
            DrawEllipse(point.Position, Colors.Red);
            isDrawing = true;
            args.Handled = true;
        }
 
        private void Canvas1_PointerMoved(object sender, PointerRoutedEventArgs args)
        {
            if (isDrawing)
            {
                PointerPoint point = args.GetCurrentPoint(Canvas1);
                DrawEllipse(point.Position, Colors.Green);
            }
 
            args.Handled = true;
        }
 
        private void Canvas1_PointerReleased(object sender, PointerRoutedEventArgs args)
        {
            PointerPoint point = args.GetCurrentPoint(Canvas1);
            DrawEllipse(point.Position, Colors.Blue);
            isDrawing = false;
            args.Handled = true;
        }
 
        private void DrawEllipse(Point pos, Color col)
        {
            const double radius = 20.0;
 
            Ellipse circle = new Ellipse
            {
                Width = radius * 2,
                Height = radius * 2,
                Fill = new SolidColorBrush(col)
            };
 
            Canvas.SetLeft(circle, pos.X - radius);
            Canvas.SetTop(circle, pos.Y - radius);
            Canvas1.Children.Add(circle);
        }
    }
}
notes/uwp/input.txt · Last modified: 2017/07/26 by leszek