c# – 如何创建不使用AdornedElement缩放的装饰器?
作者:互联网
很简单,我想创建一些调整大小/重新调整的装饰,以附加到FrameworkElement,如果他们使用正常的装饰,将允许用户调整元素的大小,如果他们使用底部,将允许他们重新调整元素的重新调整(不一定是统一) – 正确的装饰并按住SHIFT按钮,同时这样做.
我已经尝试了各种方法来实现这一目标,但我总是最终将装饰者自己缩放,因此他们最终会变得庞大,或者拥有巨大的边界.我已经开始使用相对于窗口的位置来定位它们并忽略应用于AdornedElement的RenderTransform,但是我得到了一些非常不寻常的行为.
首先,当我将元素缩放(大致)2倍时,重新缩放行为会崩溃并开始遍布整个地方.
显然,这种行为比描述更容易看到,因此为什么我附加了一个示例解决方案(VS 2010)来演示问题以及导致它的代码.
如果有人能给我任何正确方向的指示,请随时告诉我,我做错了!大声笑.
另外,要记住,如果底层装饰元素被旋转,这个装饰器最终还必须正确显示,目前它不会.
更新:为了让NVM保持高兴,以下是解决方案:NVM’s way
解决方法:
假设您在装饰器内部有用于拖动/旋转等的拇指,您首先要阻止它们进行缩放,以便您在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代码项目文章.
如果你仍然无法让它工作,请向我们展示可能导致问题的相关代码(不是视觉工作室解决方案),有人会帮助你,我相信.
编辑
首先简化您的代码以了解您的问题.
>除了btmRight拇指之外,删除所有拇指和事件处理程序.
>将一个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在第一次拖动时是正确的,因为还没有应用比例变换.拖动完成后,您将假定宽度和高度现在是新的宽度和高度.他们不是!您会看到这只是渲染变换,它不会更改元素的宽度或高度.它只是让它更大.
所以你需要做的就是先将现有的比例变换应用到Width,Height得到渲染的宽度和高度.然后使用这些新值计算比例变换并添加到变换组.然后你会得到你想要的.
在DragDelta中执行此操作时,您很可能还会遇到其他问题.但在这种情况下,你应该只用一小段相关代码询问一个更具体的问题,你肯定会在几分钟内得到某人的答案.
标签:c,scale,wpf,adorner 来源: https://codeday.me/bug/20190613/1233941.html