PreviewMouseMove两次射击

时间:2011-06-10 15:46:31

标签: c# wpf mousemove

我的简单代码有问题。我正在寻找几个小时的解决方案,但没有任何影响。 我有一个画布和矩形。我移动Rectangle,如果光标在外面,委托pMouseMove只为每个像素触发一次。相反,如果光标位于Rectangle,则delagate会为每个像素触发两次。我想只运行一次,好像它在Rectangle之外,怎么做?

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">
  <Canvas x:Name="Can" Height="257" Width="503" Background="Gray">
    <TextBox Name="tb" Width="77" Height="20" Canvas.Left="0" Canvas.Top="-21"/>
  </Canvas>
</Window>

代码隐藏:

public partial class MainWindow : Window
{
    Rectangle rect = new Rectangle();
    private static int i;
    private static string s;

    public MainWindow()
    {
        InitializeComponent();

        rect.Height = 50;
        rect.Width = 50;
        rect.Fill = Brushes.Black;
        Can.Children.Add(rect);
        Can.PreviewMouseMove += pMouseMove;
    }

    private void pMouseMove(object sender, MouseEventArgs e)
    {
        //cursor over Rectangle
        Canvas.SetTop(rect, e.GetPosition(Can).Y + 10);
        Canvas.SetLeft(rect, e.GetPosition(Can).X + 10);

        //cursor outside Rectangle
        //Canvas.SetTop(rect, e.GetPosition(Can).Y - 10);
        //Canvas.SetLeft(rect, e.GetPosition(Can).X - 10);

        //Counter
        i++;
        tb.Text = i.ToString();

        //e.Handled = true;
    }
}

抱歉我的英文不好

1 个答案:

答案 0 :(得分:3)

WPF中的事件是Routed Events,这实际上意味着您的Canvas将从画布本身和画布内的所有内容接收事件。如您所见,Canvas的{​​{1}}事件正在接收来自PreviewMouseMoveCanvas的事件。

[更新] 我运行了您的代码并添加了一行来检查Rectangle的值,以查看最初引发该事件的内容。像这样:

e.OriginalSource

我原来的答案是检查e.OriginalSource的类型,因为我以为你收到了两次相同的事件。但我现在看到你在说什么:如果private void pMouseMove(object sender, MouseEventArgs e) { // print out e.OriginalSource just for learning purposes Console.WriteLine("OriginalSource:" + e.OriginalSource.ToString()); } e.OriginalSourceRectangle事件的提升频率是PreviewMouseMove e.OriginalSource时的两倍。 Canvas的实现内部有一些内容正在执行此操作(唯一的方法是使用像Reflector这样的工具来查看内部逻辑。但是,有一种解决方法,您可以在其中制作频率事件一致。

您可以设置Rectangle,这将消除发送事件并成为rect.IsHitTestVisible = false;的矩形 - 这意味着所有e.OriginalSource事件都来自PreviewMouseMove。然后,您可以使用Canvas检查鼠标位置是否在VisualTreeHelper.HitTest内。

我刚刚在下面运行了这段代码,我认为这是一种保证事件一致性提升的方法,但仍然具有您的命中测试功能。

在构造函数中:

Rectangle

rect.Fill = Brushes.Black; rect.IsHitTestVisible = false; Can.Children.Add(rect); 处理程序中:

PreviewMouseMove