共用方式為


使用 DrawingVisual 物件

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

本主題包含下列章節。

  • 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
        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
// 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 並繪製到其中,以加入文字、圖形或影像內容。 DrawingContext 可藉由呼叫 DrawingVisual 物件的 RenderOpen 方法傳回。

若要將矩形繪製到 DrawingContext 中,請使用 DrawingContext 物件的 DrawRectangle 方法。 您也可以使用類似的方法繪製其他類型的內容。 將內容繪製到 DrawingContext 後,請呼叫 Close 方法,以關閉 DrawingContext 和保存此內容。

下列範例會建立 DrawingVisual 物件,並將矩形繪製到它的 DrawingContext

        ' 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
// 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 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


        // 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.
        Private Sub MyVisualHost_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
            ' Retreive 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
// 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;
}

請參閱

參考

DrawingVisual

HitTest

概念

WPF 圖形轉譯概觀

視覺分層中的點擊測試