Language

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

注

前のコード例を抽出した完全なコード サンプルについては、「DrawingVisuals サンプルを使用したヒット テスト 参照してください。

DrawingVisual オブジェクトの作成

DrawingVisual オブジェクトを作成すると、描画コンテンツはありません。 オブジェクトの DrawingContext を取得して描画することで、テキスト、グラフィックス、または画像のコンテンツを追加できます。 DrawingContext は、RenderOpen オブジェクトの DrawingVisual メソッドを呼び出すことによって返されます。

DrawingContextに四角形を描画するには、DrawRectangle オブジェクトの DrawingContext メソッドを使用します。 他の種類のコンテンツを描画する場合にも同様のメソッドが存在します。 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

こちらも参照ください