使用 DrawingVisual 对象

更新:2007 年 11 月

本主题概述如何在 WPF 可视层使用 DrawingVisual 对象。

本主题包括以下部分。

  • 绘制可视对象

  • DrawingVisual 宿主容器

  • 创建 DrawingVisual 对象

  • 为 FrameworkElement 成员创建重写项

  • 提供命中测试支持

  • 相关主题

DrawingVisual 对象

DrawingVisual 是一个用于呈现形状、图像或文本的轻量绘图类。此类之所以被视为轻量,是因为它不提供布局或事件处理功能,从而能够改善性能。因此,绘图最适于背景和剪贴画。

DrawingVisual 宿主容器

为了使用 DrawingVisual 对象,需要为这些对象创建一个宿主容器。该宿主容器对象必须派生自 FrameworkElement 类,该类提供 DrawingVisual 类所缺乏的布局和事件处理支持。宿主容器对象不显示任何可视属性,因为它的主要用途是包含子对象。但是,宿主容器的 Visibility 属性必须设置为 Visible;否则,它的任何子元素都将不可见。

当您为可视对象创建宿主容器对象时,需要在 VisualCollection 中存储可视对象引用。使用 Add 方法可以将可视对象添加到宿主容器中。在下面的示例中,创建一个宿主容器对象,并向它的 VisualCollection 添加三个可视对象。

// Create a host visual derived from the FrameworkElement class.
// This class provides layout, event handling, and container support for
// the child visual objects.
public class MyVisualHost : FrameworkElement
{
    // Create a collection of child visual objects.
    private VisualCollection _children;

    public MyVisualHost()
    {
        _children = new VisualCollection(this);
        _children.Add(CreateDrawingVisualRectangle());
        _children.Add(CreateDrawingVisualText());
        _children.Add(CreateDrawingVisualEllipses());

        // Add the event handler for MouseLeftButtonUp.
        this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp);
    }
说明:

有关上述代码示例所摘自的完整代码示例,请参见使用 DrawingVisual 进行命中测试示例

创建 DrawingVisual 对象

当创建 DrawingVisual 对象时,它没有绘图内容。您可以通过检索对象的 DrawingContext 并在其中进行绘制来添加文本、图形或图像内容。通过调用 DrawingVisual 对象的 RenderOpen 方法来返回 DrawingContext

要在 DrawingContext 中绘制一个矩形,应使用 DrawingContext 对象的 DrawRectangle 方法。绘制其他类型的内容存在类似方法。将内容绘制到 DrawingContext 后,调用 Close 方法来关闭 DrawingContext 并保存内容。

在下面的示例中,将创建一个 DrawingVisual 对象,并将一个矩形绘制到它的 DrawingContext 中。

// Create a DrawingVisual that contains a rectangle.
private DrawingVisual CreateDrawingVisualRectangle()
{
    DrawingVisual drawingVisual = new DrawingVisual();

    // Retrieve the DrawingContext in order to create new drawing content.
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    // Create a rectangle and draw it in the DrawingContext.
    Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
    drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);

    // Persist the drawing content.
    drawingContext.Close();

    return drawingVisual;
}

为 FrameworkElement 成员创建重写项

宿主容器对象负责管理它的可视对象集合。这需要宿主容器为派生的 FrameworkElement 类实现成员重写。

下面介绍了必须重写的两个成员:

在下面的示例中,实现了这两个 FrameworkElement 成员的重写。

// Provide a required override for the VisualChildrenCount property.
protected override int VisualChildrenCount
{
    get { return _children.Count; }
}

// Provide a required override for the GetVisualChild method.
protected override Visual GetVisualChild(int index)
{
    if (index < 0 || index >= _children.Count)
    {
        throw new ArgumentOutOfRangeException();
    }

    return _children[index];
}

提供命中测试支持

宿主容器对象即使不显示任何可视属性(但是,它的 Visibility 属性必须设置为 Visible),也可以提供事件处理。这样,您就可以为宿主容器创建事件处理例程,此例程可以捕获鼠标事件,如松开鼠标左键。然后事件处理例程可以通过调用 HitTest 方法来执行命中测试。此方法的 HitTestResultCallback 参数引用一个用户定义的过程,您可以使用此过程来确定命中测试的最终操作。

在下面的示例中,为宿主容器对象以及它的子级实现命中测试支持。

// Capture the mouse event and hit test the coordinate point value against
// the child visual objects.
void MyVisualHost_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    // Retreive the coordinates of the mouse button event.
    System.Windows.Point pt = e.GetPosition((UIElement)sender);

    // Initiate the hit test by setting up a hit test result callback method.
    VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(myCallback), new PointHitTestParameters(pt));
}

// If a child visual object is hit, toggle its opacity to visually indicate a hit.
public HitTestResultBehavior myCallback(HitTestResult result)
{
    if (result.VisualHit.GetType() == typeof(DrawingVisual))
    {
        if (((DrawingVisual)result.VisualHit).Opacity == 1.0)
        {
            ((DrawingVisual)result.VisualHit).Opacity = 0.4;
        }
        else
        {
            ((DrawingVisual)result.VisualHit).Opacity = 1.0;
        }
    }

    // Stop the hit test enumeration of objects in the visual tree.
    return HitTestResultBehavior.Stop;
}

请参见

概念

Windows Presentation Foundation 图形呈现概述

可视化层中的命中测试

参考

DrawingVisual

HitTest