很简单,我想创建一些调整大小/重新调整的装饰器以附加到FrameworkElement,如果他们正常使用装配器,则允许用户调整元素的大小,并允许他们重新调整元素(不一定是统一的),如果他们使用右下方的装饰器并按住SHIFT按钮。
我已经尝试了各种方法来实现这一目标,但我总是最终将装饰者自己缩放,因此他们最终会变得庞大,或者拥有巨大的边界。我已经开始使用相对于窗口的位置来定位它们并忽略应用于AdornedElement的RenderTransform,但是我得到了一些非常不寻常的行为。
首先, 当我将元素缩放超过(大致)2倍时,重新缩放行为会崩溃并开始在整个地方跳跃。
显然,这种行为比描述更容易看到,因此为什么我附上了一个示例问题解决方案(VS 2010)来演示问题以及导致问题的代码。
如果有人能指出正确方向,请随时告诉我,我做错了!洛尔。
另外,要记住,如果底层装饰元素被旋转,这个装饰者最终也必须正确显示,目前它不会。
更新:为了让NVM保持高兴,以下是解决方案:NVM's way
答案 0 :(得分:6)
假设您在装饰器内部有用于拖动/旋转等的拇指,您首先要阻止它们进行缩放,以便您在GetDesiredTransform覆盖中执行此操作。应用您在框架元素上应用的比例的倒数。这会使您的拇指在调整大小时不会缩放。
public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
{
double scaleFactor = GetCurrentScaleFactor(this._parent);
if (this._visualChildren != null)
{
foreach (var thumb in this._visualChildren.OfType<Thumb>())
{
thumb.RenderTransform
= new ScaleTransform(1 / scaleFactor , 1 / scaleFactor );
thumb.RenderTransformOrigin = new Point(0.5, 0.5);
}
}
return base.GetDesiredTransform(transform);
}
下一个问题是安排拇指,以便在缩放/旋转等后它们最终到达正确的位置。由于你已经改变了拇指的渲染变换,你现在还必须使用ArrangeOverride手动排列它。
为此,请保留所有拇指的清单以及它们应该处于什么位置。如果您只处理方形元素,那么您的工作就完成了一半,因为您只需处理角落和侧面。
protected override Size ArrangeOverride(Size finalSize)
{
var adornedElement = this.AdornedElement as FrameworkElement;
// Use the width/height etc of adorned element to arrange the thumbs here
// Its been a long time so either its width/height or actualwidth/actualheight
// you will need to use.
this._leftTopThumb.Arrange(Get the Rect To arrange here);
this._rightTopThumb.Arrange(Get the Rect To arrange here);
// etc
return finalSize;
}
如果您不知道如何安排填写See This代码项目文章。
如果您仍然无法让它工作,请向我们展示可能导致问题的相关代码(不是视觉工作室解决方案),有人会帮助您,我相信。
修改
首先简化代码以了解您的问题。
基本上问题代码的关键在于注释行:
void _btmRight_DragCompleted(object sender, DragCompletedEventArgs e)
{
var adornedElement = AdornedElement as FrameworkElement;
var hitThumb = sender as Thumb;
if (adornedElement == null || hitThumb == null) return;
var transformGroup = new TransformGroup();
transformGroup.Children.Add(adornedElement.RenderTransform);
//---- This is the problem line
transformGroup.Children.Add(new ScaleTransform(1 + e.HorizontalChange / adornedElement.Width, 1 + e.VerticalChange / adornedElement.Height));
//-------------------------------
adornedElement.RenderTransform = new MatrixTransform(transformGroup.Value);
}
现在很容易找出问题所在。这段代码在您第一次拖动和调整大小时效果很好。这是因为adornedElement.Width和adornedElement.Height在第一次拖动时是正确的,因为还没有应用比例变换。拖动完成后,您将假定宽度和高度现在是新的宽度和高度。 它们不是!您看到这只是一个渲染变换,它不会改变元素的宽度或高度。它只会让它更大。
所以你需要做的就是先将现有的比例变换应用到Width和Height,然后获得渲染的宽度和高度。然后使用这些新值计算比例变换并添加到变换组。然后你会得到你想要的东西。
在DragDelta中执行此操作时,您很可能还会遇到其他问题。但在这种情况下,你应该只用一小段相关代码来提出一个更具体的问题,你肯定会在几分钟内得到答案。
答案 1 :(得分:1)
Siyfion,你能看到的现象是真实的。原因是您在处理装饰器拖动时不会使用相同的缩放比例进行补偿。除了NVM的回答,请确保您也有:
double deltaX = args.HorizontalChange / CurrentDisplayScaleX;
double deltaY = args.VerticalChange / CurrentDisplayScaleX;
以相同的方式获取当前显示比例。有了这些修正后的值,跳跃就会停止。跳跃实际上是双重绘图,首先由系统自动使用错误的缩放,然后使用您提供的修改后的正确尺寸。它出现在所有规模级别,只是一旦缩放开始变大就变得非常明显。