Share via


DrawingVisual オブジェクトの使用

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

このトピックは、次のセクションで構成されています。

  • DrawingVisual オブジェクト

  • DrawingVisual ホスト コンテナー

  • DrawingVisual オブジェクトの作成

  • FrameworkElement メンバーのオーバーライドの作成

  • ヒット テストのサポート

  • 関連トピック

DrawingVisual オブジェクト

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

DrawingVisual ホスト コンテナー

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

ビジュアル オブジェクトのホスト コンテナー オブジェクトを作成する場合は、VisualCollection にビジュアル オブジェクト参照を格納する必要があります。 Add メソッドを使用して、ビジュアル オブジェクトをホスト コンテナーに追加します。 次の例では、ホスト コンテナー オブジェクトを作成し、3 つのビジュアル オブジェクトをその 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 クラスのメンバー オーバーライドを実装する必要があります。

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

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

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

次の例では、2 つの 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 グラフィックス レンダリングの概要

ビジュアル層でのヒット テスト