PreviewMouseMove 发射两次
我对简单的代码有疑问。我花了几个小时寻找解决方案,但没有效果。 我有一个画布和矩形。我移动矩形,如果光标在外部,则委托 pMouseMove 对每个像素仅触发一次。相反,如果光标位于矩形处,则 delagate 会为每个像素触发两次。我只想运行一次,就好像它在矩形之外,该怎么做?
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;
}
}
抱歉我的英语不好
I have a problem with a simple code. I was looking for a few hours a solution, but no effects.
I have a Canvas and Rectangle. I move Rectangle, if the cursor is outside, delegate pMouseMove fires only once for each pixel. Conversely, if the cursor is at the Rectangle, delagate fires twice for each pixel. I want to run it only once, as if it were outside the Rectangle, how to do it?
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>
Code-behind:
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;
}
}
Sorry for my bad english
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
WPF 中的事件是路由事件,这实际上意味着您的
Canvas 将从画布本身以及画布内的所有内容接收事件。正如您所注意到的,
Canvas
的PreviewMouseMove
事件正在接收来自Canvas
和Rectangle
的事件。[更新]
我运行了您的代码并添加了一行来检查
e.OriginalSource
的值,以查看最初引发事件的原因。像这样:我最初的答案是检查 e.OriginalSource 的类型,因为我认为您两次收到相同的事件。但我现在明白你在说什么:如果
e.OriginalSource
是Rectangle
,则PreviewMouseMove
事件的引发频率是e.OriginalSource
时的两倍code>e.OriginalSource 是Canvas
。Rectangle
的实现内部有一些东西正在执行此操作(找出答案的唯一方法是使用 Reflector 之类的工具来查看内部逻辑。但是,有一个解决方法,您可以使 所有您可以设置
rect.IsHitTestVisible = false;
,这将消除矩形发送事件和e.OriginalSource
- 这意味着PreviewMouseMove
事件将来自Canvas
然后您可以使用VisualTreeHelper.HitTest
检查鼠标位置是否在内部。 我刚刚运行了
下面的代码,我认为这是保证事件引发一致的方法,但仍然具有命中测试功能:
:
在
PreviewMouseMove
处理程序中Events in WPF are Routed Events, which effectively means that your
Canvas
will receive events from the canvas itself and everything inside the canvas. As you noticed, theCanvas
'sPreviewMouseMove
event is receiving events from both theCanvas
and theRectangle
.[Update]
I ran your code and added a line to check the value of the
e.OriginalSource
to see what originally raised the event. Like this:My original answer was to check e.OriginalSource's type because I thought you were receiving the same event twice. But I now see what you are saying: if
e.OriginalSource
is theRectangle
, thePreviewMouseMove
event gets raised twice as often compared to whene.OriginalSource
is theCanvas
. There's something internal to theRectangle
's implementation that is doing this (only way to find out is to use a tool like Reflector to see the internal logic. However, there is a workaround where you can make the frequency of the event consistent.You can set
rect.IsHitTestVisible = false;
and that will eliminate the Rectangle from sending events and beinge.OriginalSource
-- so that means allPreviewMouseMove
events will come from theCanvas
. Then you can useVisualTreeHelper.HitTest
to check to see if the mouse position is inside theRectangle
.I just ran this code below and I think this is a way to guarantee consistent raising of events, but still have your hit test capability.
In the constructor:
In the
PreviewMouseMove
handler: