繁体   English   中英

使用DrawingContext相对于中心进行绘制

[英]Draw relative to center with DrawingContext

我一直想知道如何在WPF中使用DrawingContext相对于不在控件左上角的东西进行绘制。 我的问题是我想通过连接各种点来绘制一些形状,并且这些点必须相对于主机控件的中心定位,Y指向上方。

我的元素是使用自定义DrawingVisual子类的树呈现的,其根是包含VisualCollectionBorder子类。 我通过指定ScaleTransform作为BorderRenderTransform来解决Y方向问题,本质上是垂直翻转整个控件。

但是,在其他问题上没有这样的运气。 关于如何使我的血统居中的想法吗?

可以使用MatrixTransform代替ScaleTransform,该MatrixTransform在y方向上按-1缩放并将坐标原点平移到控件的中心。 但是,每当控件大小更改时,都必须更新此转换。 因此,您将像下面那样重写OnRenderSizeChanged(假设您设置了控件的RenderTransform属性):

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
    base.OnRenderSizeChanged(sizeInfo);

    RenderTransform = new MatrixTransform(1d, 0d, 0d, -1d,
        sizeInfo.NewSize.Width / 2d, sizeInfo.NewSize.Height / 2d);
}

编辑:如果您不想转换整个控件,则还可以将MatrixTransform定义为类成员,并将其应用于视觉子级集合中的每个Visual。

private MatrixTransform transform = new MatrixTransform();

分配给每个新Visual的Transform属性:

ContainerVisual visual = ...
visual.Transform = transform;

关于大小更改,您只需更新该MatrixTransform:

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
    base.OnRenderSizeChanged(sizeInfo);

    transform.Matrix = new Matrix(1d, 0d, 0d, -1d,
        sizeInfo.NewSize.Width / 2d, sizeInfo.NewSize.Height / 2d);
}

当然,您只需要将“变换”应用于“顶级”视觉效果即可。 这些视觉效果的孩子将通过父母的改造而改变。 我不完全了解如何通过“包含VisualCollection的Border子类”管理视觉效果。 典型的方法是将一个父ContainerVisual作为视觉树的根。 然后,仅将变换应用于此基本视觉效果。

您尝试过TranslateTransform吗?

好吧,我明白了。 这是我的方法。

首先,我定义了一个GroupTransform并分配给我的Border子类的WorldTransform属性。

var trans = new TranslateTransform();
var conv = new HalfConverter(); // a custom converter that halves whatever you pass to it
BindingOperations.SetBinding(trans, TranslateTransform.XProperty, new Binding { Path = new PropertyPath(ActualWidthProperty), Source = this, Converter = conv });
BindingOperations.SetBinding(trans, TranslateTransform.YProperty, new Binding { Path = new PropertyPath(ActualHeightProperty), Source = this, Converter = conv });

WorldTransform = new TransformGroup();
WorldTransform.Children.Add(new ScaleTransform { ScaleY = -1.0 });
WorldTransform.Children.Add(trans);
VisualTransform = WorldTransform;

然后,当我创建自定义DrawingVisual的新实例时,将其Transform属性分配给WorldTransform

// ZoneVisual is my DrawingVisual subclass
var vis = new ZoneVisual(zone) { Transform = WorldTransform };

当我添加一个新元素(顺便说一下,是一个Node )时,我只需要通过WorldTransform的逆来对其进行转换。

这可能不是最好的方法,但似乎效果很好。 我对高性能的需求不高,因此它可能会胜任。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM