Jeff Maner
Jeff Maner

Reputation: 1179

Jumpy and Incomplete XAML Window Drag with C# TouchMove

I have a small undecorated xaml window for a touch screen. The user must be able to move the window using touch and drag. Currently on touch and drag, the window moves in the direction of the drag, but only part way; and there appears to be two windows rather than one, making the touch and drag appear jumpy.

This behavior manifests on the development system (Surface Pro 3 using Visual Studio Professional 2015) as well as on the production system (Windows 7, no keyboard or mouse).

I based this C# on Microsoft's example.

using System.Windows;
using System.Windows.Input;

namespace XAMLApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private TouchDevice windowTouchDevice;
        private Point lastPoint;

        private void Circle_TouchUp(object sender, TouchEventArgs e)
        {
            // Do stuff.
        }

        private void Window_TouchDown(object sender, TouchEventArgs e)
        {
            e.TouchDevice.Capture(this);

            if (windowTouchDevice == null)
            {
                windowTouchDevice = e.TouchDevice;
                lastPoint = windowTouchDevice.GetTouchPoint(null).Position;
            }

            e.Handled = true;
        }

        private void Window_TouchMove(object sender, TouchEventArgs e)
        {
            if (e.TouchDevice == windowTouchDevice)
            {
                var currentTouchPoint = windowTouchDevice.GetTouchPoint(null);

                var deltaX = currentTouchPoint.Position.X - lastPoint.X;
                var deltaY = currentTouchPoint.Position.Y - lastPoint.Y;

                Top += deltaY;
                Left += deltaX;

                lastPoint = currentTouchPoint.Position;

                e.Handled = true;
            }
        }

        private void Window_TouchLeave(object sender, TouchEventArgs e)
        {
            if (e.TouchDevice == windowTouchDevice)
                windowTouchDevice = null;

            e.Handled = true;
        }
    }
}

And here's some xaml for the window.

<Window x:Name="AppWindow" x:Class="XAMLApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:XAMLApp"
        mc:Ignorable="d"
        Title="XAML Application"
        Height="25" Width="25"
        AllowsTransparency="True" WindowStyle="None" ResizeMode="NoResize"
        ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden"
        ShowInTaskbar="False" ToolTip="XAML Application" Topmost="True" UseLayoutRounding="True"
        MaxHeight="25" MaxWidth="25" MinHeight="25" MinWidth="25"
        Left="0" Top="0" Background="Transparent"
        TouchDown="Window_TouchDown"
        TouchMove="Window_TouchMove"
        TouchLeave="Window_TouchLeave">
    <Grid>
        <Ellipse x:Name="Circle" Fill="Black" HorizontalAlignment="Left"
                 Height="24" Margin="0" Stroke="Black" VerticalAlignment="Top"
                 Width="24" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden"
                 TouchUp="Circle_TouchUp" />
    </Grid>
</Window>

I've tried replacing the Grid with a Canvas. That made no difference. I also tried using Manipulation as demonstrated by Microsoft. When trying to drag the window, I was told that the transformation was invalid for the window.

How can I make the touch and drag behave the same as DragMove() using a left-mouse-click-and-drag?

Upvotes: 0

Views: 429

Answers (2)

andreask
andreask

Reputation: 4298

The TouchPoint retrieved through the TouchDevice.GetTouchPoint method and the window's Top and Left attributes do not share the same coordinate system. All you need to do is convert the X and Y values retrieved to screen coordinates:

private void Window_TouchMove(object sender, TouchEventArgs e)
{
    if (e.TouchDevice == windowTouchDevice)
    {
        var currentTouchPoint = windowTouchDevice.GetTouchPoint(null);

        var locationOnScreen = this.PointToScreen(new Point(currentTouchPoint.Position.X, currentTouchPoint.Position.Y));

        var deltaX = locationOnScreen.X - lastPoint.X;
        var deltaY = locationOnScreen.Y - lastPoint.Y;

        Top += deltaY;
        Left += deltaX;

        lastPoint = locationOnScreen;

        e.Handled = true;
    }
}

EDIT:

Of course, the thing about different coordinate systems applies to the whole project, so the Window_TouchDown event handler method needs to be adapted in a similar way:

private void Window_TouchDown(object sender, TouchEventArgs e)
{
    e.TouchDevice.Capture(this);

    if (windowTouchDevice == null)
    {
        windowTouchDevice = e.TouchDevice;
        var currentTouchPoint = windowTouchDevice.GetTouchPoint(null);
        var locationOnScreen = this.PointToScreen(new Point(currentTouchPoint.Position.X, currentTouchPoint.Position.Y));
        lastPoint = locationOnScreen;
    }

    e.Handled = true;
}

Upvotes: 1

Jeff Maner
Jeff Maner

Reputation: 1179

Instead of

Top += deltaY;
Left += deltaX;

I just needed

Top += currentTouchPoint.Position.Y;
Left += currentTouchPoint.Position.X;

Ugh.

Upvotes: 0

Related Questions