用DrawtContext绘制相对于中心



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

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

不过,另一个问题没有这样的运气。有什么想法将我的起源集中?

而不是scaletransform,您可以使用沿y方向缩放-1并将坐标原点转换为控件中心的矩阵transform。但是,每当控件的尺寸变化时,都必须更新此转换。因此,您将覆盖如下所示(假设您设置了控件的 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定义为类成员,并将其应用于视觉儿童集合中的每个视觉效果。

private MatrixTransform transform = new MatrixTransform();

分配到每个新视觉的转换属性:

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);
}

当然,您只需要将转换应用于"顶级"视觉效果。这些视觉效果的孩子将因父母的转变而改变。我不完全理解您如何通过"包含可录像带的边框子类"管理视觉效果。典型的方法是将一个 parent contuntervisual作为视觉树的根。然后将变换仅应用于此根视觉。

您是否尝试过翻译?

好吧,我明白了。这就是我做的。

首先,我定义了一个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的倒数来转换它。

瞧。这可能不是最好的方法,但似乎运行良好。我没有非常高的性能需求,所以它可能会完成工作。

最新更新