鼠标移动事件在光标处于画布外时仍会被调用

3

我不知道我的代码或WPF是否有问题,但问题在于:我想创建一个小程序,在画布上使用光标绘图。我有一个简单的WPF窗口:

<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="475" Width="544">
<Grid>    
    <Grid.RowDefinitions>
        <RowDefinition Height="100px"></RowDefinition>
        <RowDefinition Height ="*"></RowDefinition>
        <RowDefinition Height="100px"></RowDefinition>
    </Grid.RowDefinitions>    
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100px"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="100px"></ColumnDefinition>
    </Grid.ColumnDefinitions>
        <Canvas Grid.Row="1" Grid.Column="1"  Name="imageCanvas" MouseEnter="StackPanel_MouseEnter" MouseLeave="StackPanel_MouseLeave" Background="LightGray" 
                      MouseDown="StackPan_MouseDown" MouseUp="StackPan_MouseUp" MouseMove="StackPan_MouseMove">

        </Canvas>        
</Grid>

这里是背景代码:

   private void StackPan_MouseDown(object sender, MouseButtonEventArgs e)
    {
        draw = true;
    }

    private void StackPan_MouseUp(object sender, MouseButtonEventArgs e)
    {
        draw = false;
    }

    private void StackPan_MouseMove(object sender, MouseEventArgs e)
    {
        if (draw)
        {
            var pos = Mouse.GetPosition(imageCanvas);
            Rectangle rec = new Rectangle()
                    {
                        Width = 10,
                        Height = 10,
                        Fill = Brushes.Red,
                    };
            Canvas.SetTop(rec, pos.Y);
            Canvas.SetLeft(rec, pos.X);
            imageCanvas.Children.Add(rec);
        }

    }

我的工作是以下内容: https://www.dropbox.com/s/7moq4p8f8f409b3/wpf_canvas.png

当光标在画布之外时,为什么会调用StackPan_MouseMove函数?

这里有一个可执行文件,你可以注意到这种行为: https://www.dropbox.com/s/ye1w2j9chld2oif/WpfApplication1.exe

2个回答

1
你可以通过Canvas的Rectangle子元素获取MouseMove事件。
虽然最好使用InkPresenter或InkCanvas(如用户keyboardP所说),但你可以将矩形设为不可见以进行命中测试。然后它们将不再产生任何输入事件。
Rectangle rec = new Rectangle()
{
    Width = 10,
    Height = 10,
    Fill = Brushes.Red,
    IsHitTestVisible = false // here
};

好的,那么我如何在画布外创建矩形? - Vahagn Nahapetyan
谢谢,Clemens。我会看一下InkPresenter/IncCanvas。 - Vahagn Nahapetyan

1

尝试将Canvas放在一个Border控件内,并将Border控件的ClipToBounds属性设置为true

<Border ClipToBounds="true" Grid.Row="1" Grid.Column="1" >
    <Canvas Name="imageCanvas" MouseEnter="StackPanel_MouseEnter" MouseLeave="StackPanel_MouseLeave" Background="LightGray" 
            MouseDown="StackPan_MouseDown" MouseUp="StackPan_MouseUp" MouseMove="StackPan_MouseMove">
    </Canvas>
</Border>

稍微说一下,看起来InkPresenter/InkCanvas可能更适合你要做的控件,除非你有特定的原因不想使用它们。


添加边框有助于解决问题,非常感谢。 我尝试使用MouseLeave事件,但问题是当光标在画布外时也会调用MouseEnter。 - Vahagn Nahapetyan
不客气 :) 在看到您的XAML已经包含它之后,我删除了MouseLeave部分。 - keyboardP

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