如何创建没有';t使用AdornedElement缩放

本文关键字:使用 缩放 AdornedElement 何创建 创建 | 更新日期: 2023-09-27 18:27:27

很简单,我想创建一些调整大小/重新缩放的装饰器来附加到FrameworkElement,如果用户正常使用装饰器,它将允许用户调整元素的大小;如果用户使用右下角的装饰器并在这样做的同时按住SHIFT按钮,它将允许用户重新缩放元素(不一定统一)。

我尝试了各种方法来实现这一点,但我总是以装饰物本身的规模而告终,所以它们最终会变得巨大,或者有巨大的边界。从那以后,我开始使用相对于窗口的位置来定位它们,并忽略了应用于AdornedElement的RenderTransform,但我得到了一些非常不寻常的行为。

首先,当我将元素缩放超过(大致)2倍时,重新缩放行为会崩溃,并开始到处跳跃

显然,这种行为更容易看到而不是描述,因此我附上了一个示例解决方案(VS 2010),演示了这个问题和导致它的代码

示例VS 2010解决方案

如果有人能给我任何正确的方向,请随时告诉我我做错了!lol.

此外,请记住,如果底层装饰元素被旋转,这个装饰器最终也必须正确显示,而目前不会。

更新:为了让NVM满意,这里有一个解决方案:NVM的方式

如何创建没有';t使用AdornedElement缩放

假设装饰器中有拇指用于拖动/旋转等,则首先需要阻止它们进行缩放,因此可以在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;
}

如果你不知道如何安排事情,请参阅这篇代码项目文章。

如果你仍然无法让它发挥作用,请向我们展示可能会引起问题的相关代码(而不是visual studio解决方案),我相信会有人帮助你。

编辑

首先简化代码以理解问题。

  1. 删除除btmRight拇指之外的所有拇指和事件处理程序
  2. 将DragCompleted事件添加到btmRight Thumb。(删除阻力增量)

从本质上讲,问题代码的关键可以归结为注释行:

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是正确的,因为还没有应用缩放变换。拖动完成后,假设"宽度"answers"高度"现在将是新的宽度和高度他们不是您可以看到这只是一个渲染变换,它不会改变元素的宽度或高度。它只是将其渲染得更大。

因此,您需要首先将现有的比例变换应用于"宽度"answers"高度",以获得渲染的宽度和高度。然后使用这些新值计算缩放变换,并将其添加到变换组中。然后你就会得到你想要的。

在DragDelta中执行此操作时,您很可能仍会遇到其他问题。但在这种情况下,你应该只使用相关代码中的一小部分来问一个更具体的问题,我相信你会在几分钟内从某人那里得到答案。

Siyfion,你能看到的现象是真实的。原因是在处理装饰器拖动时,没有使用相同的缩放进行补偿。除了NVM的答案,确保你也有这个:

double deltaX = args.HorizontalChange / CurrentDisplayScaleX;
double deltaY = args.VerticalChange / CurrentDisplayScaleX;

在那里您可以以相同的方式获得当前显示比例。有了这些校正值,跳跃将停止。跳跃实际上是双重绘制,首先是系统自动使用错误的缩放比例,其次是使用您提供的修改后的正确尺寸。它出现在所有的缩放级别,只是当缩放开始变大时,它变得非常明显。