DrawingVisual オブジェクトの使用

このトピックでは、WPF のビジュアル層で DrawingVisual オブジェクトを使用する方法の概要を示します。

DrawingVisual オブジェクト

DrawingVisual は、図形、イメージ、またはテキストのレンダリングに使用する軽量の描画クラスです。 このクラスが軽量と見なされる理由は、レイアウトやイベントの処理を行わないことで、パフォーマンスが向上するからです。 そのため、背景やクリップ アートの描画に適しています。

DrawingVisual ホスト コンテナー

DrawingVisual オブジェクトを使用するには、このオブジェクトのホスト コンテナーを作成する必要があります。 ホスト コンテナー オブジェクトは、FrameworkElement クラスから派生させる必要があります。これにより、レイアウトやイベントの処理がサポートされます。これは、DrawingVisual クラスには欠落しているものです。 ホスト コンテナー オブジェクトの主な目的は子オブジェクトを格納することなので、ホスト コンテナー オブジェクトでは可視プロパティは表示されません。 ただし、ホスト コンテナーの Visibility プロパティは、Visible に設定する必要があります。このようにしないと、その子要素は一切表示されません。

ビジュアル オブジェクトのホスト コンテナー オブジェクトを作成する際には、VisualCollection にビジュアル オブジェクト参照を格納する必要があります。 ホスト コンテナーにビジュアル オブジェクトを追加するには、Add メソッドを使用します。 次の例では、ホスト コンテナー オブジェクトを作成し、その VisualCollection に 3 つのビジュアル オブジェクトを追加しています。

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

注意

上記のコードの抽出元となった完全なコード サンプルについては、「DrawingVisual を使用したヒット テストのサンプル」を参照してください。

Creating DrawingVisual オブジェクトの作成

DrawingVisual オブジェクトを作成した時点では、その中に描画コンテンツは含まれていません。 テキスト、グラフィックス、またはイメージ コンテンツを追加するには、オブジェクトの DrawingContext を取得し、その中に描画します。 DrawingContext を取得するには、DrawingVisual オブジェクトの RenderOpen メソッドを呼び出します。

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 クラスのメンバーのオーバーライドを実装する必要があります。

オーバーライドする必要がある 2 つのメンバーを次に示します。

  • GetVisualChild:子要素のコレクションから、指定したインデックス位置の子を返します。

  • VisualChildrenCount:この要素内でビジュアル子要素の数を取得します。

次の例では、2 つの 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

関連項目