当在包含两个Image的Canvas上更改UIElement.CaptureMouse()的调用顺序时,我得到不同的结果

时间:2017-07-19 09:14:11

标签: c# wpf

我现在只是想尝试使用平移和缩放创建一个简单的图像查看器来学习WPF。

我写了这样的XAML代码:

<Window x:Class="PanningImageTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PanningImageTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Border Name="panBorder" ClipToBounds="True">
            <Canvas Name="panImage" MouseLeftButtonDown="Image_MouseLeftButtonDown"
                MouseMove="Image_MouseMove"
                MouseLeftButtonUp="Image_MouseLeftButtonUp">
                <!-- Two Image is intended, as in real situation,
                     they will use different sources -->
                <Image Source="Wallpaper.jpg" Stretch="None"/>
                <Image Source="Wallpaper.jpg" Stretch="None"/>
            </Canvas>
        </Border>
    </Grid>
</Window>

并编写了我的代码:     使用System.Windows;     使用System.Windows.Media;

namespace PanningImageTest
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private Point _start;
        private Point _origin;

        private void Image_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.panImage.CaptureMouse();

            _start = e.GetPosition(this.panBorder);
            _origin.X = this.panImage.RenderTransform.Value.OffsetX;
            _origin.Y = this.panImage.RenderTransform.Value.OffsetY;
        }

        private void Image_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (!this.panImage.IsMouseCaptured)
            {
                return;
            }

            Point mousePos = e.GetPosition(this.panBorder);

            Matrix matrix = this.panImage.RenderTransform.Value;
            matrix.OffsetX = _origin.X + (mousePos.X - _start.X);
            matrix.OffsetY = _origin.Y + (mousePos.Y - _start.Y);

            this.panImage.RenderTransform = new MatrixTransform(matrix);
        }

        private void Image_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.panImage.ReleaseMouseCapture();
        }
    }
}

如果我在this.panImage.CaptureMouse()行前调用_start = ... etc ... ,则只要我点击图片上的某个位置,所有图片就会传送到鼠标位置。

像这样: Call before

但如果我在之后调用相同的函数,如下所示,它只是按预期工作:

    _start = e.GetPosition(this.panBorder);
    _origin.X = this.panImage.RenderTransform.Value.OffsetX;
    _origin.Y = this.panImage.RenderTransform.Value.OffsetY;

    this.panImage.CaptureMouse();

像这样: Call After

如果我在Image中只使用一个Canvas标记,则在两种情况下都可以正常使用。 我尝试更改.NET版本,将事件移至Border而不是Canvas,但所有内容都无法解释这些结果。

我不知道为什么会这样。任何人都可以给出一些解释吗?

2 个答案:

答案 0 :(得分:1)

即使MouseLeftButtonDown方法尚未完成,

CaptureMouse() method事件也已开始被触发。

因此,您将if (!this.panImage.IsMouseCaptured) { return; } 作为最后一行,并使用以下检查作为警卫,以防止在您尚未获得 _origin 的值时拖动图像。

40 x 35 x 55
60 x 35 x 25
55 x 45 x 30
110 x 55 x 45
45 x 30 x 33

答案 1 :(得分:0)

您需要在开始计算偏移之前设置起始位置和坐标。否则你会得到偏移错误。因此,在完成此操作之前捕获鼠标是没有意义的。

请注意,移动鼠标后会立即引发MouseMove事件(基本上一直都是这样),但在捕获它之前,事件处理程序只会通过设置其{{}而不移动图像而返回1}}属性。

因此,您应该设置起始位置以及X和Y坐标,然后根据这些坐标移动图像。不是相反。