WPF无法从MouseDown事件中获取触摸位置。

5
我有一个WPF项目,在.NET(v4.0)添加触摸支持之前编写,因此仅处理了鼠标事件。当我在带有手指的触摸屏上测试项目时,就会遇到这个问题。
问题是,在第一次触摸时正确检索到位置(X,Y),但是无论我在哪里触摸,即使我触摸图像外部,都会保持(X,Y)值相同,并触发MouseDown事件,这使得它更加奇怪。
它可以在.NET 3.0 / 3.5 / 4.0上重现,在Win7 / Win8上进行测试,两者都是64位。似乎是MouseDown事件出现了问题,而MouseUp正常工作。
更新:
这是一个有悠久历史的bug,微软甚至在4.5中也没有修复它,所以如果你遇到相同的症状,你必须更新代码-从Touch事件获取触摸位置,而不是从Mouse事件获取。幸运的是,这个bug并不难以察觉,所以定位和修复只需要很短的时间。
复现该问题的代码:
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>

代码后台:

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());
        }
    }
}
2个回答

2

在WPF中,默认情况下,如果一个控件没有处理触摸事件,它会被转换成鼠标事件。触摸事件是路由事件,因此当鼠标事件被触发时,它将上下遍历可视树(因此即使您在图像之外触摸,您的事件处理程序也会被执行)。

如果MouseDown事件来自于一个被转换的触摸事件,您可以使用StylusDevice获取正确的位置:

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

或者,作为替代方案,您可以为需要位置的控件添加TouchDown事件的处理程序:

<Image TouchDown="UIElement_OnTouchDown"/>

 private void UIElement_OnTouchDown(object sender, TouchEventArgs e)
 {
      var touchPoint = e.GetTouchPoint(sender as Image);
      // more processing using touchPoint.Position
 }

是的,处理TouchDown事件对我来说有效。但在我看来,这更像是框架本身的一个明显bug,因为与鼠标点击良好配合的传统代码应该能够很好地与触摸配合使用。 - kennyzx
@kennyzx,我能够使用一个新的示例项目来重现这个问题,所以看起来这可能是一个问题,或者只是触摸支持添加的方式。 - Adrian Fâciu

0

如果您在 .NET 4.5.0 中运行,您将不会看到此问题。它是在4.5.1中引入的。我正在尝试看看能否让微软的某个人注意并修复此问题,而无需您和我修改我们的代码。


我会在4.5中检查它。 - kennyzx
不幸的是,这没有任何区别,我已经尝试重新定向到4.5和4.5.1,但没有成功。 - kennyzx
抱歉,我花了太多时间在这上面弄乱了。添加touchdown修复对于4.5.0是必要且足够的。同时,在4.5.1及以后的版本中,我还需要添加显式的stylusdown处理。 - osoblanco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接