gpt4 book ai didi

c# - PreviewMouseMove 触发两次

转载 作者:行者123 更新时间:2023-11-30 16:29:26 24 4
gpt4 key购买 nike

我有一个简单代码的问题。我一直在寻找几个小时的解决方案,但没有效果。我有一个 Canvas 和矩形。我移动矩形,如果光标在外面,委托(delegate) pMouseMove 只为每个像素触发一次。相反,如果光标位于矩形上,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;
}
}

抱歉我的英语不好

最佳答案

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

[更新]我运行了您的代码并添加了一行来检查 e.OriginalSource 的值,以查看最初引发事件的原因。像这样:

private void pMouseMove(object sender, MouseEventArgs e)
{
// print out e.OriginalSource just for learning purposes
Console.WriteLine("OriginalSource:" + e.OriginalSource.ToString());
}

我最初的回答是检查 e.OriginalSource 的类型,因为我认为您收到了两次相同的事件。但我现在明白你在说什么了:如果 e.OriginalSourceRectangle,则 PreviewMouseMove 事件的引发频率是 时的两倍code>e.OriginalSourceCanvasRectangle 的实现内部有一些东西正在执行此操作(唯一的方法是使用 Reflector 之类的工具来查看内部逻辑。但是,有一种解决方法可以使事件发生频率一致。

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

我刚刚在下面运行了这段代码,我认为这是一种保证一致引发事件的方法,但仍然具有您的 HitTest 能力。

在构造函数中:

rect.Fill = Brushes.Black;
rect.IsHitTestVisible = false;
Can.Children.Add(rect);

PreviewMouseMove 处理程序中:

private void pMouseMove(object sender, MouseEventArgs e)
{
// Debug.WriteLine(e.OriginalSource.ToString());

HitTestResult result = VisualTreeHelper.HitTest(rect, e.GetPosition(sender as UIElement));

if (result != null) {
Debug.WriteLine("Mouse inside rect")
}
else {
Debug.WriteLine("Mouse outside rect");
}
}

关于c# - PreviewMouseMove 触发两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6308814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com