ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C#-PreviewMouseMove触发两次

2019-12-08 09:08:24  阅读:386  来源: 互联网

标签:mousemove wpf c


我有一个简单的代码问题.我在找几个小时的解决方案,但没有效果.
我有一个画布和矩形.我移动Rectangle,如果光标在外部,则对每个像素,代表pMouseMove仅触发一次.相反,如果光标位于“矩形”上,则每个像素的延迟激发两次.我只想运行一次,就好像它在矩形外面一样,该怎么办呢?

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的PreviewMouseMove事件正在接收来自Canvas和Rectangle的事件.

[更新]
我运行了您的代码,并添加了一行代码来检查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.OriginalSource是Rectangle,则与e.OriginalSource是Canvas时相比,引发PreviewMouseMove事件的频率是原来的两倍.为此,Rectangle的实现内部有一些东西(唯一的发现方法是使用Reflector之类的工具查看内部逻辑.但是,有一种解决方法可以使事件的频率保持一致.

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

我只是在下面运行了这段代码,我认为这是保证事件持续发生的一种方法,但是仍然具有点击测试功能.

在构造函数中:

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");
    }
}

标签:mousemove,wpf,c
来源: https://codeday.me/bug/20191208/2090433.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有