Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF could not get touch position from MouseDown event

Tags:

c#

wpf

touch

I have a WPF project written before touch support was added to .NET (v 4.0), so only the mouse events were handled. I run into this problem when testing the project on a touch screen with fingers.

The problem is, the position (X, Y) is correctly retrieved in the first touch, but the (X, Y) values stay the same in subsequent touches, no matter where I touch, and even if I touch out of the Image, the MouseDown event is fired, which makes it more weird.

It can be reproduced with .NET 3.0/3.5/4.0, tested on Win7/Win8, both are 64 bits. And it seems it is MouseDown event that is misbehaving, MouseUp works fine.

Update:

This is a bug with long history and MS has not yet fixed it (even in 4.5), so you have to update the code if you encounter the same symptom - get the touch position from Touch event, not Mouse event. Luckily this bug is not subtle so it only takes a little while to be located and fixed.

Code to reproduce the issue:

XAML:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Image Height="60" Width="80" x:Name="Image" MouseDown="Image_MouseDown" 
                Source="/WpfApplication1;component/Images/Desert.jpg" />
    </Grid> 
</Window>

Code behind:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Image_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Point p = e.GetPosition(Image);
            MessageBox.Show(p.X.ToString() + " " + p.Y.ToString());
        }
    }
}
like image 638
kennyzx Avatar asked Nov 02 '22 05:11

kennyzx


1 Answers

By default in WPF, if a Touch event is not handled by a control it will be promoted to a Mouse event. Touch events are routed events, so when the Mouse event will be triggered it will go up and down the visual tree (hence your event handler being executed even when you touch outside of the Image).

If the MouseDown event comes from a promoted touch event, you could probably get the correct position using the StylusDevice:

if (e.StylusDevice != null)
    point = e.StylusDevice.GetPosition(sender as Image);

Or as an alternative, you could add a handler for the TouchDown event for the controls where you need the position:

<Image TouchDown="UIElement_OnTouchDown"/>

 private void UIElement_OnTouchDown(object sender, TouchEventArgs e)
 {
      var touchPoint = e.GetTouchPoint(sender as Image);
      // more processing using touchPoint.Position
 }
like image 178
Adrian Fâciu Avatar answered Nov 15 '22 04:11

Adrian Fâciu