0

WPF。

(我预先申请了看似代码墙,但问题对我来说似乎很复杂,我希望尽可能完整)。

我有一个放在 InkCanvas 上的图像:

在调整大小显示之前:在此处输入图像描述

在 DragDelts 期间调整路径轮廓显示:在此处输入图像描述

拖动完成后。注意: 我希望左上角位于“X”的位置,即 DRAGCOMPLETE 时光标所在的位置在此处输入图像描述

这是我用来实现上述图像的代码。本质上,问题归结为在调整图像大小后计算正确的平移变换。我已经尝试了所有我能想到的但没有成功。真正令人困惑的是,光标的偏移量似乎在某种程度上取决于图像被放到 InkCanvas 上的位置。也就是说,如果图像被放置在更靠近左边界的位置,则偏移量会比放置在中心位置时更加明显。非常混乱。

private void IC_Drop(object sender, DragEventArgs e)
    {
        InkCanvas ic = sender as InkCanvas;

        ic.EditingMode = InkCanvasEditingMode.None;

        ImageInfo image_Info = e.Data.GetData(typeof(ImageInfo)) as ImageInfo;
        if (image_Info != null)
        { 
            Image image = new Image();
            image.Width = image_Info.Width * 4;
            image.Stretch = Stretch.Fill;           
            image.Source = new BitmapImage(image_Info.Uri);

            Point position = e.GetPosition(ic);
            TranslateTransform mov = new TranslateTransform(position.X, position.Y);
            image.RenderTransform = mov;
            ic.Children.Add(image);
            ImageResizing imgResize = ImageResizing.Create(image);
        }
    }

ImageResizing.Create() 现在将 rendertransforms 和 thumb 装饰器添加到图像以调整大小、移动和旋转:

private ImageResizing(Image image)
    {
        if (image == null)
            throw new ArgumentNullException("image");

       _image = image;

        ScaleTransform scale = new ScaleTransform();
        RotateTransform rot = new RotateTransform();
        TranslateTransform mov = new TranslateTransform();

        TransformGroup tg = new TransformGroup();
        tg.Children.Add(image.RenderTransform);  
        tg.Children.Add(scale);                  
        tg.Children.Add(rot);                    
        tg.Children.Add(mov);                     
        image.RenderTransform = tg; 
        image.RenderTransformOrigin = new Point(0.5,0.5);

        // Create the adorner.
        _adorner = new MyImageAdorner(image);

        // Get the Adorner Layer and add the Adorner.
        InstallAdorner();
 }

TopLeft Thumb 装饰器定义为:

  Thumb topLeft;
  Path outline;

  public MyImageAdorner(UIElement adornedElement)
      : base(adornedElement)
    {
        visualChildren = new VisualCollection(this);

        // Initialize the Resizing (i.e., corner) thumbs with specialized cursors.
        BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);
        topLeft.DragDelta += new DragDeltaEventHandler(TopLeft_DragDelta);
        topLeft.DragCompleted += TopLeft_DragCompleted;
    }

   // Helper method to instantiate the corner Thumbs, set the Cursor property, 
    // set some appearance properties, and add the elements to the visual tree.
    void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
    {
        if (cornerThumb != null) return;

        cornerThumb = new Thumb();

        // Set some arbitrary visual characteristics.
        cornerThumb.Cursor = customizedCursor;
        cornerThumb.Height = cornerThumb.Width = 15;
        cornerThumb.Opacity = 0.40;
        cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue);

        visualChildren.Add(cornerThumb);
    }

我正在使用 DragDelta 将轮廓路径元素定位到最终所需的大小,如下所示:

 // Top Left Corner is being dragged. Anchor is Bottom Right.

    void TopLeft_DragDelta(object sender, DragDeltaEventArgs e)
    {
        ScaleTransform sT = new ScaleTransform(1 - e.HorizontalChange / outline.ActualWidth, 1 - e.VerticalChange / outline.ActualHeight,
            outline.ActualWidth, outline.ActualHeight);

        outline.RenderTransform = sT;   
    }

请注意,我打算使用左上角从右下角调整图像大小。因此,随着左上角被拖动,图像的所有点都将远离右下角。

最后,我使用 DragCompleted 事件在图像上实际执行新的渲染:

  private void TopLeft_DragCompleted(object sender, DragCompletedEventArgs e)
    {
        // Get new scaling from the Outline.
        ScaleTransform sT = outline.RenderTransform as ScaleTransform;
        double anchorX = sT.CenterX;
        double anchorY = sT.CenterY;

        // Get the previous scaling
        TransformGroup gT = AdornedElement.RenderTransform as TransformGroup;
        ScaleTransform sT0 = gT.Children[1] as ScaleTransform;
        double oldscaleX = sT0.ScaleX;
        double oldscaleY = sT0.ScaleY;

        double oldCenterX = anchorX - (outline.ActualWidth ) * oldscaleX;
        double oldCenterY = anchorY - (outline.ActualHeight) * oldscaleY;

        // Get the previous translation
        TranslateTransform tT = gT.Children[3] as TranslateTransform;

        sT0.CenterX = anchorX;
        sT0.CenterY = anchorY;

        sT0.ScaleX *= sT.ScaleX;
        sT0.ScaleY *= sT.ScaleY;

        double newCenterX = anchorX -(outline.ActualWidth) * sT0.ScaleX;
        double newCenterY = anchorY -(outline.ActualHeight) * sT0.ScaleY;

        tT.X += newCenterX - oldCenterX;
        tT.Y += newCenterY - oldCenterY;

        // Put transforms back.
        gT.Children[1] = sT0;
        gT.Children[3] = tT;

        AdornedElement.RenderTransform = gT;
        outline.RenderTransform = Transform.Identity;  

    }

为了完整起见,装饰器被定位为:

  protected override Size ArrangeOverride(Size finalSize)
    {
        double eW = AdornedElement.RenderSize.Width;
        double eH = AdornedElement.RenderSize.Height;
        FrameworkElement ele = AdornedElement as FrameworkElement;
        EnforceSize(ele);
        eH = ele.Height;
        eW = ele.Width;

        Size aS = new Size(eW, eH);

        // calculate the center of the image.
        var center = new Point(eW / 2, eH / 2);

        topLeft.Arrange(new Rect(new Point(-center.X, -center.Y), aS));
        topRight.Arrange(new Rect(new Point(center.X, -center.Y), aS));
        bottomLeft.Arrange(new Rect(new Point(-center.X, center.Y), aS));
        bottomRight.Arrange(new Rect(new Point(center.X, center.Y), aS));

        // The RotateHandle is placed slightly above the Top of the Image center.
        // The MoveHandle is placed at the center of the Image.
        rotateHandle.Arrange(new Rect(new Point(0, -(center.Y + HANDLEMARGIN)), aS));
        moveHandle.Arrange(new Rect(new Point(0, 0), aS));

        // Place a blue outline arround the image.
        outline.Data = new RectangleGeometry(new Rect(aS));
        outline.Arrange(new Rect(aS));

        // Return the final size.
        return aS;
    }

我一定会很感激任何帮助或建议。我究竟做错了什么?

TIA

注意:这个问题的答案是缩放导致倾斜

4

0 回答 0