2016-08-19 81 views
2

因此,我开始从http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part开始着眼于MoveResizeRotate项目并进行构建。调整翻转和旋转的图像的大小

我已经添加了几件事情:

  • 使用宽高比,如果您拖动角拇指调整的能力。
  • 使用ScaleTransform(即ScaleX = -1)翻转x轴上的ContentControl的功能。

但是,现在我在调整控件大小时遇到​​了麻烦。它在旋转之前工作正常,但旋转后,它似乎从中间而不是那个角落/侧面调整大小。当控件的ScaleX设置为-1时,这尤其明显。

这里是我的ResizeThumb代码:

namespace ResizeRotateFlip 
{ 
    public class ResizeThumb : Thumb 
    { 
     private double angle; 
     private Point transformOrigin; 
     private ContentControl designerItem; 

     public ResizeThumb() 
     { 
      DragStarted += new DragStartedEventHandler(this.ResizeThumb_DragStarted); 
      DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta); 
     } 

     private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e) 
     { 
      this.designerItem = DataContext as ContentControl; 

      if(this.designerItem != null) 
      { 
       this.transformOrigin = this.designerItem.RenderTransformOrigin; 
       RotateTransform rotateTransform = this.designerItem.RenderTransform as RotateTransform; 

       if(rotateTransform != null) 
       { 
        this.angle = rotateTransform.Angle * Math.PI/180.0; 
       } 
       else 
       { 
        this.angle = 0; 
       } 
      } 
     } 

     private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e) 
     { 
      if(this.designerItem != null) 
      { 
       //variables 
       double deltaVertical = 0, deltaHorizontal = 0; 
       double newHeight = 0, newWidth = 0; 

       double startHeight = this.designerItem.Height; 
       double startWidth = this.designerItem.Width; 

       //calculate deltas 
       switch(VerticalAlignment) 
       { 
        case System.Windows.VerticalAlignment.Bottom: 
         deltaVertical = Math.Min(-e.VerticalChange, this.designerItem.ActualHeight - this.designerItem.MinHeight); 
         break; 
        case System.Windows.VerticalAlignment.Top: 
         deltaVertical = Math.Min(e.VerticalChange, this.designerItem.ActualHeight - this.designerItem.MinHeight); 
         break; 
        default: 
         break; 
       } 
       switch(HorizontalAlignment) 
       { 
        case System.Windows.HorizontalAlignment.Left: 
         deltaHorizontal = Math.Min(e.HorizontalChange, this.designerItem.ActualWidth - this.designerItem.MinWidth); 
         break; 
        case System.Windows.HorizontalAlignment.Right: 
         deltaHorizontal = Math.Min(-e.HorizontalChange, this.designerItem.ActualWidth - this.designerItem.MinWidth); 
         break; 
        default: 
         break; 
       }  

       // resize 
       if(dragging_from_corner()) 
       { 
        newHeight = this.designerItem.Height - deltaVertical; 
        newWidth = this.designerItem.Width - deltaHorizontal; 

        if(newHeight >= 0 && newWidth >= 0) 
        { 
         aspect_ratio_resizing(this.designerItem.Height, this.designerItem.Width, newHeight, newWidth); 
        } 
       } 
       else 
       { 
        this.designerItem.Height -= deltaVertical; 
        this.designerItem.Width -= deltaHorizontal; 
       }  

       // translate 
       double verticalChange = startHeight - this.designerItem.Height; 
       double horizontalChange = startWidth - this.designerItem.Width; 

       TransformGroup transformGroup = designerItem.RenderTransform as TransformGroup; 
       ScaleTransform scaleTransform = transformGroup.Children[(int)TransformType.ScaleTransform] as ScaleTransform; 

       switch(VerticalAlignment) 
       { 
        case System.Windows.VerticalAlignment.Bottom: 
         if(scaleTransform.ScaleY != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + verticalChange * Math.Cos(-this.angle) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + verticalChange * Math.Sin(-this.angle) - (this.transformOrigin.Y * verticalChange * Math.Sin(-this.angle))); 
         } 
         break; 
        case System.Windows.VerticalAlignment.Top: 
         if(scaleTransform.ScaleY != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + verticalChange * Math.Cos(-this.angle) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + verticalChange * Math.Sin(-this.angle) - (this.transformOrigin.Y * verticalChange * Math.Sin(-this.angle))); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
         } 
         break; 
        default: 
         break; 
       } 
       switch(HorizontalAlignment) 
       { 
        case System.Windows.HorizontalAlignment.Left: 
         if(scaleTransform.ScaleX != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + horizontalChange * Math.Sin(this.angle) - this.transformOrigin.X * horizontalChange * Math.Sin(this.angle)); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + horizontalChange * Math.Cos(this.angle) + (this.transformOrigin.X * horizontalChange * (1 - Math.Cos(this.angle)))); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) - this.transformOrigin.X * horizontalChange * Math.Sin(this.angle)); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + (horizontalChange * this.transformOrigin.X * (1 - Math.Cos(this.angle)))); 
         } 
         break; 
        case System.Windows.HorizontalAlignment.Right: 
         if(scaleTransform.ScaleX != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) - this.transformOrigin.X * horizontalChange * Math.Sin(this.angle)); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + (horizontalChange * this.transformOrigin.X * (1 - Math.Cos(this.angle)))); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + horizontalChange * Math.Sin(this.angle) - this.transformOrigin.X * horizontalChange * Math.Sin(this.angle)); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + horizontalChange * Math.Cos(this.angle) + (this.transformOrigin.X * horizontalChange * (1 - Math.Cos(this.angle)))); 
         } 
         break; 
        default: 
         break; 
       }     
      } 

      e.Handled = true; 
     } 

     private bool dragging_from_corner() 
     { 
      if((VerticalAlignment == VerticalAlignment.Top || VerticalAlignment == VerticalAlignment.Bottom) && 
       (HorizontalAlignment == HorizontalAlignment.Left || HorizontalAlignment == HorizontalAlignment.Right)) 
      { 
       return true; 
      } 

      return false; 
     } 

     private void aspect_ratio_resizing(double originalHeight, double originalWidth, double newHeight, double newWidth) 
     { 
      double ratioWidth = newWidth/originalWidth; 
      double ratioHeight = newHeight/originalHeight; 
      double ratio = Math.Min(ratioWidth, ratioHeight); 

      if(originalHeight * ratio > this.designerItem.MinHeight && originalWidth * ratio > this.designerItem.MinWidth) 
      { 
       this.designerItem.Height = originalHeight * ratio; 
       this.designerItem.Width = originalWidth * ratio; 
      } 
     } 
    } 
} 

这里是我的RotateThumb代码:

namespace ResizeRotateFlip 
{ 
    public class RotateThumb : Thumb 
    { 
     private Point centerPoint; 
     private Vector startVector; 
     private double initialAngle; 
     private Canvas designerCanvas; 
     private ContentControl designerItem; 

     public RotateThumb() 
     { 
      DragDelta += new DragDeltaEventHandler(this.RotateThumb_DragDelta); 
      DragStarted += new DragStartedEventHandler(this.RotateThumb_DragStarted); 
     } 

     private void RotateThumb_DragStarted(object sender, DragStartedEventArgs e) 
     { 
      this.designerItem = DataContext as ContentControl; 

      if(this.designerItem != null) 
      { 
       this.designerCanvas = VisualTreeHelper.GetParent(this.designerItem) as Canvas; 

       if(this.designerCanvas != null) 
       { 
        this.centerPoint = this.designerItem.TranslatePoint(
         new Point(this.designerItem.Width * this.designerItem.RenderTransformOrigin.X, 
            this.designerItem.Height * this.designerItem.RenderTransformOrigin.Y), 
            this.designerCanvas); 

        Point startPoint = Mouse.GetPosition(this.designerCanvas); 
        this.startVector = Point.Subtract(startPoint, this.centerPoint); 

        TransformGroup transformGroup = this.designerItem.RenderTransform as TransformGroup; 
        RotateTransform rotateTransform = transformGroup.Children[(int)TransformType.RotateTransform] as RotateTransform; 

        if(rotateTransform == null) 
        { 
         initialAngle = 0; 
        } 
        else 
        { 
         this.initialAngle = rotateTransform.Angle; 
        } 
       } 
      } 
     } 

     private void RotateThumb_DragDelta(object sender, DragDeltaEventArgs e) 
     { 
      if(this.designerItem != null && this.designerCanvas != null) 
      { 
       TransformGroup transformGroup = this.designerItem.RenderTransform as TransformGroup; 
       ScaleTransform scaleTransform = transformGroup.Children[(int)TransformType.ScaleTransform] as ScaleTransform; 

       double multiplier = scaleTransform.ScaleX * scaleTransform.ScaleY; 

       Point currentPoint = Mouse.GetPosition(this.designerCanvas); 
       Vector deltaVector = Point.Subtract(currentPoint, this.centerPoint); 

       double angle = Vector.AngleBetween(this.startVector, deltaVector); 

       RotateTransform rotateTransform = transformGroup.Children[(int)TransformType.RotateTransform] as RotateTransform; 
       rotateTransform.Angle = this.initialAngle + (Math.Round(angle, 0)) * multiplier; 

       this.designerItem.InvalidateMeasure(); 
      } 
     } 
    } 
} 

我猜我的X和Y的变化(在ResizeThumb)计算是不正确的。因此,在调整大小后,翻译不能正确应用。虽然我已经注意到我对RotateThumb所作的更改会对调整大小产生影响,但在RotateThumb中使用TransformGroup之前,控件在旋转时会正确调整大小。

这个项目我已经提到的用途:

case System.Windows.VerticalAlignment.Bottom: 
     Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
     Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
    break; 

计算X & Y表示实例的新位置:但我不知道如何在控制翻转计算此。 - 我应该注意,我在这里使用verticalChange而不是deltaVertical的原因是,当使用deltaHorizo​​ntal和deltaVertical时,控件倾向于围绕画布移动。

我想我的问题是更多的数学方面,如何计算X & Y的新位置,当控制旋转和翻转?


编辑 一个我刚才注意到的事情是在ResizeThumb的DragStarted方法,我还没有访问我的TransformGroup的RotateTransform。

我已经改变了:

RotateTransform rotateTransform = this.designerItem.RenderTransform as RotateTransform; 

到:

TransformGroup transformGroup = designerItem.RenderTransform as TransformGroup; 
RotateTransform rotateTransform = transformGroup.Children[(int)TransformType.RotateTransform] as RotateTransform; 

这解决了大小调整是错了,当的scaleX和scaleY没有改变,但我仍然得到调整的问题时,我翻了一下控制。

回答

1

我想我已经解决了!现在我明白了这一点非常明显。

的翻译我这样做:

switch(VerticalAlignment) 
       { 
        case System.Windows.VerticalAlignment.Bottom: 
         if(scaleTransform.ScaleY != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + verticalChange * Math.Cos(-this.angle) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + verticalChange * Math.Sin(-this.angle) - (this.transformOrigin.Y * verticalChange * Math.Sin(-this.angle))); 
         } 
         break; 
        case System.Windows.VerticalAlignment.Top: 
         if(scaleTransform.ScaleY != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + verticalChange * Math.Cos(-this.angle) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + verticalChange * Math.Sin(-this.angle) - (this.transformOrigin.Y * verticalChange * Math.Sin(-this.angle))); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
         } 
         break; 
        default: 
         break; 
       } 

我在那里只是用从VerticalAlignment.Top为VeticalAlignment.Bottom计算时,则scaleY设置为-1。反之亦然。但是,对于Canvas.SetLeft来说这是没有意义的。

所以不是我把它改为:

switch(VerticalAlignment) 
       { 
        case System.Windows.VerticalAlignment.Bottom: 
         if(scaleTransform.ScaleY != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + verticalChange * Math.Cos(-this.angle) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 

         } 
         if(scaleTransform.ScaleX != -1) 
         { 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
         } 
         else 
         { 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + verticalChange * Math.Sin(-this.angle) - (this.transformOrigin.Y * verticalChange * Math.Sin(-this.angle))); 
         } 
         break; 
        case System.Windows.VerticalAlignment.Top: 
         if(scaleTransform.ScaleY != -1) 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + verticalChange * Math.Cos(-this.angle) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
         } 
         else 
         { 
          Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * verticalChange * (1 - Math.Cos(-this.angle)))); 
         } 
         if(scaleTransform.ScaleX != -1) 
         { 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + verticalChange * Math.Sin(-this.angle) - (this.transformOrigin.Y * verticalChange * Math.Sin(-this.angle))); 
         } 
         else 
         { 
          Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - verticalChange * this.transformOrigin.Y * Math.Sin(-this.angle)); 
         } 
         break; 
        default: 
         break; 
       } 

现在机顶盒和SetLeft设置适当的根据自己的尺度。