共用方式為


使用 DrawingVisual 物件

本主題提供如何在 WPF 視覺層中使用 DrawingVisual 物件的概觀。

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);
    }
' 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
    Inherits FrameworkElement
    ' Create a collection of child visual objects.
    Private _children As VisualCollection

    Public Sub New()
        _children = New VisualCollection(Me)
        _children.Add(CreateDrawingVisualRectangle())
        _children.Add(CreateDrawingVisualText())
        _children.Add(CreateDrawingVisualEllipses())

        ' Add the event handler for MouseLeftButtonUp.
        AddHandler MouseLeftButtonUp, AddressOf MyVisualHost_MouseLeftButtonUp
    End Sub

備註

如需前述程式碼範例的完整程式碼,請參閱「使用 DrawingVisuals 進行點選測試範例」。

建立 DrawingVisual 物件

當您創建一個DrawingVisual物件時,它沒有任何繪圖內容。 您可以取得物件的DrawingContext,並在其中繪製以新增文字、圖形或影像內容。 呼叫 RenderOpen 方法的 DrawingVisual 物件會傳回 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;
}
' Create a DrawingVisual that contains a rectangle.
Private Function CreateDrawingVisualRectangle() As DrawingVisual
    Dim drawingVisual As New DrawingVisual()

    ' Retrieve the DrawingContext in order to create new drawing content.
    Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

    ' Create a rectangle and draw it in the DrawingContext.
    Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
    drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)

    ' Persist the drawing content.
    drawingContext.Close()

    Return drawingVisual
End Function

針對 FrameworkElement 成員建立重寫

主機容器物件負責管理其視覺物件的集合。 這需要主機容器實現衍生類別的成員覆寫FrameworkElement

下列清單說明您必須覆寫的兩個成員︰

  • GetVisualChild:從子元素集合中傳回位於指定索引的子項。

  • VisualChildrenCount:取得在此元素中視覺子元素的數量。

在下列範例中,兩個 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];
}


' Provide a required override for the VisualChildrenCount property.
Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
    Get
        Return _children.Count
    End Get
End Property

' Provide a required override for the GetVisualChild method.
Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
    If index < 0 OrElse index >= _children.Count Then
        Throw New ArgumentOutOfRangeException()
    End If

    Return _children(index)
End Function

提供碰撞測試支援

即使主機容器物件未顯示任何可見屬性,也可以提供事件處理,不過,必須將其 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)
{
    // Retrieve 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;
}
' Capture the mouse event and hit test the coordinate point value against
' the child visual objects.
Private Sub MyVisualHost_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    ' Retrieve the coordinates of the mouse button event.
    Dim pt As Point = e.GetPosition(CType(sender, UIElement))

    ' Initiate the hit test by setting up a hit test result callback method.
    VisualTreeHelper.HitTest(Me, Nothing, New HitTestResultCallback(AddressOf myCallback), New PointHitTestParameters(pt))
End Sub

' If a child visual object is hit, toggle its opacity to visually indicate a hit.
Public Function myCallback(ByVal result As HitTestResult) As HitTestResultBehavior
    If result.VisualHit.GetType() Is GetType(DrawingVisual) Then
        If (CType(result.VisualHit, DrawingVisual)).Opacity = 1.0 Then
            CType(result.VisualHit, DrawingVisual).Opacity = 0.4
        Else
            CType(result.VisualHit, DrawingVisual).Opacity = 1.0
        End If
    End If

    ' Stop the hit test enumeration of objects in the visual tree.
    Return HitTestResultBehavior.Stop
End Function

另請參閱