因此,我开始从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的原因是,当使用deltaHorizontal和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没有改变,但我仍然得到调整的问题时,我翻了一下控制。