Windows Presentation Foundation のグラフィックス レンダリングの概要

更新 : 2007 年 11 月

ここでは、WPF のビジュアル層の概要について説明します。WPF モデルのレンダリング サポートに関する Visual クラスの役割に重点を置いて説明します。

このトピックには次のセクションが含まれています。

  • ビジュアル オブジェクトの役割
  • ビジュアル オブジェクトを使用してコントロールをビルドする方法
  • ビジュアル ツリー
  • ビジュアル レンダリング動作
  • VisualTreeHelper クラス
  • 関連トピック

ビジュアル オブジェクトの役割

Visual クラスは、すべての FrameworkElement オブジェクトの派生元となる基本抽象クラスです。また、このクラスは、WPF で新しいコントロールを作成するためのエントリ ポイントとしても機能し、多くの点で Win32 アプリケーション モデルのウィンドウ ハンドル (HWND) と考えることができます。

Visual オブジェクトは、WPF の中心的なオブジェクトであり、その第一の役割は描画をサポートすることです。Button および TextBox などのユーザー インターフェイス コントロールは、Visual クラスから派生し、このクラスを使用して描画データを保持します。Visual オブジェクトは、以下をサポートしています。

  • 出力表示 : ビジュアルのシリアル化された永続的な描画内容を表示します。

  • 変換 : ビジュアルで変換を実行します。

  • クリッピング : ビジュアルのクリッピング領域をサポートします。

  • ヒット テスト : 座標またはジオメトリがビジュアルの境界内に含まれているかどうかを判断します。

  • 境界ボックスの計算 : ビジュアルの外接する四角形を決定します。

ただし、Visual オブジェクトでは、次のような描画以外の機能はサポートしていません。

  • イベント処理

  • レイアウト

  • スタイル

  • データ バインディング

  • グローバリゼーション

Visual は、パブリック抽象クラスとして公開され、子クラスはこのクラスから派生する必要があります。WPF で公開されるビジュアル オブジェクトの階層構造を次の図に示します。

Visual クラスの階層構造

Visual オブジェクトから派生したクラスのダイアグラム

DrawingVisual クラス

DrawingVisual は、図形、イメージ、またはテキストの描画に使用する軽量の描画クラスです。このクラスが軽量と見なされる理由は、レイアウトやイベントの処理を実現しないため、実行時のパフォーマンスが向上するからです。このため、背景やクリップ アートの描画に適しています。DrawingVisual を使用すると、カスタム ビジュアル オブジェクトを作成できます。詳細については、「DrawingVisual オブジェクトの使用」を参照してください。

Viewport3DVisual クラス

Viewport3DVisual は、2D VisualVisual3D オブジェクト間のブリッジを提供します。Visual3D クラスは、すべての 3D ビジュアル要素の基本クラスです。Viewport3DVisual では、Camera 値と Viewport 値を定義する必要があります。カメラを使用するとシーンを表示できます。ビューポートは、投影が 2D サーフェイス上にマップされる場所を設定します。WPF の 3D の詳細については、「3-D グラフィックスの概要」を参照してください。

ContainerVisual クラス

ContainerVisual クラスは、Visual オブジェクトのコレクションのコンテナとして使用されます。DrawingVisual クラスは、ContainerVisual クラスから派生するため、ビジュアル オブジェクトのコレクションを格納できます。

ビジュアル オブジェクトの描画コンテンツ

Visual オブジェクトは、レンダリング データをベクタ グラフィックス命令リストとして格納します。命令リスト内の各項目は、シリアル化された形式のグラフィックス データおよび関連リソースの低レベル セットを表します。描画コンテンツを格納可能なレンダリング データには次の 4 種類があります。

描画コンテンツの種類

説明

ベクタ グラフィックス

ベクタ グラフィックス データと、関連する Brush および Pen の情報を表します。

イメージ

Rect で定義されている領域内のイメージを表します。

グリフ

指定したフォント リソースからの一連のグリフである GlyphRun をレンダリングする描画を表します。これはテキストの表示方法です。

モニタ

ビデオをレンダリングする描画を表します。

DrawingContext を使用すると、Visual にビジュアル コンテンツを読み込むことができます。DrawingContext オブジェクトの描画コマンドを使用すると、リアルタイムで画面に描画するのではなく、実際にはグラフィックス システムで今後使用する一連のレンダリング データが格納されます。

Button などの WPF コントロールを作成した場合、そのコントロールは、それ自身を描画するためのレンダリング データを暗黙的に生成します。たとえば、ButtonContent プロパティを設定すると、グリフのレンダリング表現がコントロールに格納されます。

Visual のコンテンツは、DrawingGroup 内の 1 つ以上の Drawing オブジェクトとして表されます。DrawingGroup は、コンテンツに適用される不透明マスク、変換、ビットマップ効果などの操作も表します。コンテンツがレンダリングされるときには、OpacityMaskOpacityBitmapEffectClipGeometryGuidelineSet、そして Transform の順に DrawingGroup 操作が適用されます。

レンダリング シーケンス中に DrawingGroup 操作が適用される順序を次の図に示します。

DrawingGroup 操作の順序

操作の DrawingGroup 順序

詳細については、「Drawing オブジェクトの概要」を参照してください。

ビジュアル層での描画コンテンツ

DrawingContext を直接インスタンス化することはできませんが、DrawingGroup.OpenDrawingVisual.RenderOpen などの一部のメソッドから描画コンテキストを取得できます。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;
}

ビジュアル層で描画コンテンツを列挙する

Drawing オブジェクトは、他の用途に加えて、Visual のコンテンツを列挙するためのオブジェクト モデルも提供します。

メモ :

ビジュアルのコンテンツの列挙の際には、ベクタ グラフィックス命令リストとして基になるレンダリング データ表現を取得しているのではなく、Drawing オブジェクトを取得しています。

GetDrawing メソッドを使用して、VisualDrawingGroup 値を取得し列挙する例を次に示します。

public void RetrieveDrawing(Visual v)
{
    DrawingGroup dGroup = VisualTreeHelper.GetDrawing(v);
    EnumDrawingGroup(dGroup);

}

 // Enumerate the drawings in the DrawingGroup.
 public void EnumDrawingGroup(DrawingGroup drawingGroup)
 {
     DrawingCollection dc = drawingGroup.Children;

     // Enumerate the drawings in the DrawingCollection.
     foreach (Drawing drawing in dc)
     {
         // If the drawing is a DrawingGroup, call the function recursively.
         if (drawing.GetType() == typeof(DrawingGroup))
         {
             EnumDrawingGroup((DrawingGroup)drawing);
         }
         else if (drawing.GetType() == typeof(GeometryDrawing))
         {
             // Perform action based on drawing type.  
         }
         else if (drawing.GetType() == typeof(ImageDrawing))
         {
             // Perform action based on drawing type.
         }
         else if (drawing.GetType() == typeof(GlyphRunDrawing))
         {
             // Perform action based on drawing type.
         }
         else if (drawing.GetType() == typeof(VideoDrawing))
         {
             // Perform action based on drawing type.
         }
     }
 }

ビジュアル オブジェクトを使用してコントロールをビルドする方法

WPF のオブジェクトの多くは、他のビジュアル オブジェクトで構成されています。これは、子孫オブジェクトのさまざまな階層をこれらのオブジェクトに格納できることを意味します。WPF のユーザー インターフェイス要素 (コントロールなど) の多くは、さまざまな種類のレンダリング要素を表す複数のビジュアル オブジェクトで構成されています。たとえば、Button コントロールは、ClassicBorderDecoratorContentPresenterTextBlock など他の多数のオブジェクトを格納できます。

次のコードは、マークアップで定義されている Button コントロールを示しています。

<Button Click="OnClick">OK</Button>

既定の Button コントロールを構成するビジュアル オブジェクトを列挙すると、次の図に示すビジュアル オブジェクトの階層がわかります。

ビジュアル ツリー階層の図

ビジュアル ツリー階層のダイアグラム

Button コントロールには ClassicBorderDecorator 要素が含まれており、さらにこの要素には ContentPresenter 要素が含まれています。ClassicBorderDecorator 要素は、Button の境界線と背景を描画します。ContentPresenter 要素は、Button の内容を表示します。この場合、テキストを表示しているため、ContentPresenter 要素には TextBlock 要素が格納されています。Button コントロールは ContentPresenter を使用します。これは、Image やジオメトリ (EllipseGeometry など) など他の要素でコンテンツを表現できるということを意味します。

コントロール テンプレート

コントロールをコントロールの階層に拡張する場合、ControlTemplate が重要になります。コントロール テンプレートは、コントロールの既定のビジュアル階層を指定します。コントロールを明示的に参照すると、コントロールのビジュアル階層が暗黙的に参照されます。コントロール テンプレートの既定値をオーバーライドして、コントロールの外観をカスタマイズできます。たとえば、Button コントロールの背景色の値を変更して、純色値の代わりに線形グラデーション値を使用することができます。詳細については、「Button ControlTemplate の例」を参照してください。

Button コントロールなどのユーザー インターフェイス要素には、コントロールのすべてのレンダリング定義を表す複数のベクタ グラフィックス命令リストが含まれています。次のコードは、マークアップで定義されている Button コントロールを示しています。

<Button Click="OnClick">
  <Image Source="images\greenlight.jpg"></Image>
</Button>

Button コントロールを構成するビジュアル オブジェクトとベクタ グラフィックス命令リストを列挙すると、次の図に示すビジュアル オブジェクトの階層がわかります。

ビジュアル ツリーおよびレンダリング データの図

ビジュアル ツリーおよび描画データのダイアグラム

Button コントロールには ClassicBorderDecorator 要素が含まれており、さらにこの要素には ContentPresenter 要素が含まれています。ClassicBorderDecorator 要素は、ボタンの境界線と背景を構成する個々のグラフィックス要素をすべて描画します。ContentPresenter 要素は、Button の内容を表示します。この場合、イメージを表示しているため、ContentPresenter 要素には Image 要素が格納されています。

ビジュアル オブジェクトとベクタ グラフィックス命令リストの階層については、次の点に注意する必要があります。

  • 階層内の順序は、描画情報のレンダリング順序を表します。子要素は、ルート ビジュアル要素を起点として、左から右、上から下に走査されます。要素が子ビジュアル要素を持つ場合、子ビジュアル要素は要素の兄弟の前に走査されます。

  • 階層内の非リーフ要素 (ContentPresenter など) は子要素の格納に使用されます。これらの要素には、命令リストは格納されません。

  • ベクタ グラフィックス命令リストとビジュアル子の両方がビジュアル要素に含まれている場合、ビジュアル子オブジェクトが描画される前に、親ビジュアル要素の命令リストがレンダリングされます。

  • ベクタ グラフィックス命令リスト内の項目は、左から右の順にレンダリングされます。

ビジュアル ツリー

ビジュアル ツリーには、アプリケーションのユーザー インターフェイスで使用するすべてのビジュアル要素が含まれます。ビジュアル要素には永続化された描画情報が含まれているため、ビジュアル ツリーは、ディスプレイ デバイスへの出力を構成するのに必要なレンダリング情報をすべて含むシーン グラフであると考えることができます。このツリーは、コードかマークアップかを問わず、アプリケーションで直接作成されたすべてのビジュアル要素を累積したものです。ビジュアル ツリーには、コントロールやデータ オブジェクトなどの要素のテンプレート拡張によって作成されたビジュアル要素もすべて含まれます。

マークアップで定義された StackPanel 要素を次のコードに示します。

<StackPanel>
  <Label>User name:</Label>
  <TextBox />
  <Button Click="OnClick">OK</Button>
</StackPanel>

マークアップ例の StackPanel 要素を構成するビジュアル オブジェクトを列挙すると、次の図に示すビジュアル オブジェクトの階層がわかります。

ビジュアル ツリー階層の図

ビジュアル ツリー階層のダイアグラム

レンダリング順序

ビジュアル ツリーは、WPF のビジュアル オブジェクトと描画オブジェクトの表示順序を決定します。検査の順序は、ビジュアル ツリーの最上位ノードであるルート ビジュアルで始まります。次に、ルート ビジュアルの子が左から右に走査されます。ビジュアルが子を持つ場合、子はビジュアルの兄弟の前に走査されます。つまり、子ビジュアルの内容は、そのビジュアル自体の内容の前に表示されます。

ビジュアル ツリー レンダリング順序の図

ビジュアル ツリー描画順序のダイアグラム

ルート ビジュアル

ルート ビジュアルは、ビジュアル ツリー階層内の最上位の要素です。ほとんどのアプリケーションでは、ルート ビジュアルの基本クラスは Window または NavigationWindow のいずれかです。ただし、ビジュアル オブジェクトを Win32 アプリケーションでホストする場合は、Win32 ウィンドウにホストする最上位のビジュアルがルート ビジュアルになります。詳細については、「チュートリアル : Win32 アプリケーションでのビジュアル オブジェクトのホスト」を参照してください。

論理ツリーとの関係

WPF の論理ツリーは、実行時のアプリケーションの要素を表します。このツリーを直接操作することはありませんが、アプリケーションのこのビューは、プロパティの継承やイベントのルーティングを理解する上で役立ちます。ビジュアル ツリーとは異なり、論理ツリーは、ListItem などのビジュアル データ オブジェクト以外のオブジェクトを表すことができます。多くの場合、論理ツリーはアプリケーションのマークアップ定義にほぼ一致します。マークアップで定義された DockPanel 要素を次のコードに示します。

<DockPanel>
  <ListBox>
    <ListBoxItem>Dog</ListBoxItem>
    <ListBoxItem>Cat</ListBoxItem>
    <ListBoxItem>Fish</ListBoxItem>
  </ListBox>
  <Button Click="OnClick">OK</Button>
</DockPanel>

マークアップ例の DockPanel 要素を構成する論理オブジェクトを列挙すると、次の図に示す論理オブジェクトの階層がわかります。

論理ツリーの図

ツリー ダイアグラム

ビジュアル ツリーおよび論理ツリーは、現在のアプリケーション要素のセットと同期し、要素の追加、削除、または変更をすべて反映します。ただし、ツリーにはアプリケーションの異なるビューが表示されます。ビジュアル ツリーとは異なり、論理ツリーでは、コントロールの ContentPresenter が展開されません。これは、論理ツリーとビジュアルツリーが同一のオブジェクト セットに対して 1 対 1 で直接対応しないということを意味します。実際、同一の要素をパラメータとして使用して、LogicalTreeHelper オブジェクトの GetChildren メソッドと VisualTreeHelper オブジェクトの GetChild メソッドを呼び出すと、異なる結果が返されます。

論理ツリーの詳細については、「WPF のツリー」を参照してください。

XamlPad を使用したビジュアル ツリーの表示

WPF ツールである XamlPad は、現在定義されているXAML コンテンツに対応するビジュアル ツリーを表示および探索するためのオプションを提供します。ビジュアル ツリーを表示するには、メニュー バーの [Show Visual Tree] ボタンをクリックします。XamlPad の [Visual Tree Explorer] パネルのビジュアル ツリー ノードに展開された XAML コンテンツを次の図に示します。

XamlPad の Visual Tree Explorer パネル

XamlPad のビジュアル ツリー エクスプローラ パネル

XamlPad の [Visual Tree Explorer] パネルでは、LabelTextBox、および Button の各コントロールが別々のビジュアル オブジェクト階層を表示していることに注意してください。これは、WPF コントロールにそのコントロールのビジュアル ツリーを含む ControlTemplate があるためです。コントロールを明示的に参照すると、コントロールのビジュアル階層が暗黙的に参照されます。

ビジュアル パフォーマンスのプロファイリング

WPF は、アプリケーションの実行時の動作を分析したり、適用可能なパフォーマンス最適化の種類を決定できるパフォーマンス プロファイリング ツール スイートを提供します。ビジュアル プロファイラ ツール スイートでは、アプリケーションのビジュアル ツリーに直接マップすることにより、パフォーマンス データを多彩なグラフィカル ビューで示します。このスクリーンショットでは、ビジュアル プロファイラの [CPU 使用率] セクションに、レンダリングやレイアウトなど、WPF サービスのオブジェクトの使用率の詳細が示されています。

ビジュアル プロファイラ表示出力

Visual Profiler 表示出力

WPF のパフォーマンス ツールの詳細については、「WPF のパフォーマンス プロファイリング ツール」を参照してください。

ビジュアル レンダリング動作

WPF では、保持モード グラフィックス、ベクタ グラフィックス、デバイスに依存しないグラフィックスといった、ビジュアル オブジェクトのレンダリング動作に影響を及ぼす機能が導入されています。

保持モード グラフィックス

ビジュアル オブジェクトの役割を理解するためには、即時モードのグラフィックス システムと保持モードのグラフィックス システムの違いについて理解することが重要です。GDI または GDI+ に基づく標準的な Win32 アプリケーションでは、即時モードのグラフィックス システムが使用されます。これは、ウィンドウのサイズ変更やオブジェクトの外観の変更などのアクションによって無効化されたクライアント領域の部分を、アプリケーションが再描画するということを意味します。

Win32 レンダリング シーケンスの図

Win32 レンダリング シーケンスのダイアグラム

一方、WPF では、保持モード システムが使用されます。これは、外観を持つアプリケーション オブジェクトがシリアル化された一連の描画データを定義するということを意味します。描画データが定義された後は、アプリケーション オブジェクトをレンダリングするために、システムがすべての再描画要求に応答します。実行時であっても、アプリケーション オブジェクトを変更または作成し、描画要求に対する応答を引き続きシステムに任せることができます。保持モードのグラフィックス システムでは、アプリケーションによって描画情報が常にシリアル化された状態に保たれます。ただし、レンダリングはシステムによって実行されます。これは保持モードのグラフィックス システムの長所です。次の図は、アプリケーションが描画要求への応答で WPF に依存しているしくみを示しています。

WPF レンダリング シーケンスの図

WPF レンダリング シーケンスのダイアグラム

高度な再描画

保持モード グラフィックスを使用することの最も大きな利点の 1 つは、WPF がアプリケーション内の再描画を必要とする項目を効率的に最適化できることです。さまざまな不透明度を持つ複雑なシーンがある場合でも、特別な目的を持つコードを記述して再描画を最適化する必要は通常ありません。これと Win32 プログラミングを比較してください。Win32 プログラミングでは、更新領域での再描画量を最小化してアプリケーションを最適化するのに多大な労力を費やすことがあります。Win32 アプリケーションでの再描画の最適化に関連する複雑さの例については、「Redrawing in the Update Region」を参照してください。

ベクタ グラフィックス

WPF では、ベクタ グラフィックスがレンダリング データ形式として使用されます。スケーラブル ベクタ グラフィックス (SVG)、Windows メタファイル (.wmf)、TrueType フォントなどのベクタ グラフィックスは、レンダリング データを格納し、グラフィックス プリミティブを使用してイメージを再作成する方法を表す命令リストとして送信します。たとえば、TrueType フォントは、ピクセル配列ではなく、直線、曲線、およびコマンドのセットを表すアウトライン フォントです。ベクタ グラフィックスの主な利点の 1 つは、任意のサイズおよび解像度にスケーリングできることです。

ベクタ グラフィックスとは異なり、ビットマップ グラフィックスは、特定の解像度で事前にレンダリングされたピクセル単位のイメージ表現としてレンダリング データを格納します。ビットマップ グラフィックス形式とベクタ グラフィックス形式の主な違いの 1 つは、元のソース イメージへの忠実性です。たとえば、ソース イメージのサイズを変更した場合、ビットマップ グラフィックス システムではイメージが伸縮されます。一方、ベクタ グラフィックス システムでは、イメージがスケーリングされるため、イメージの忠実性が保持されます。

3 倍に拡大されたソース イメージを次の図に示します。ソース イメージをビットマップ グラフィックス イメージとして伸縮した場合、イメージにゆがみが生じることに注意してください。ベクタ グラフィックス イメージとしてスケーリングした場合、こうしたゆがみは生じません。

ラスタ グラフィックスとベクタ グラフィックスの違い

ラスタ グラフィックスとベクタ グラフィックスの違い

次のマークアップでは、2 つの Path 要素を定義しています。2 番目の要素では、ScaleTransform を使用して、最初の要素の描画命令を 3 倍に拡大しています。Path 要素の描画命令は変更されないことに注意してください。

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" />

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" >
  <Path.RenderTransform>
    <ScaleTransform ScaleX="3.0" ScaleY="3.0" />
  </Path.RenderTransform>
</Path>

解像度およびデバイスに依存しないグラフィックスについて

画面上のテキストとグラフィックスのサイズを決定するシステム要素には、解像度と DPI の 2 つがあります。解像度は、画面に表示されるピクセルの数を表します。解像度が高くなるとピクセルが小さくなり、グラフィックスとテキストがより滑らかに表示されます。解像度が 1024 x 768 に設定されたモニタに表示されるグラフィックスは、解像度を 1600 x 1200 に変更すると、一段と小さく表示されます。

もう 1 つのシステム設定である DPI は、画面上の 1 インチのサイズをピクセル単位で表したものです。ほとんどの Windows システムは 96 DPI であり、これは、画面上の 1 インチが 96 ピクセルであることを意味します。DPI の設定を上げると、画面上の 1 インチが長くなり、設定を下げると、画面上の 1 インチが短くなります。このため、画面上の 1 インチと実際の 1 インチは同じサイズでなく、ほとんどのシステムで異なる可能性があります。DPI を大きくすると、画面上の 1 インチのサイズが大きくなるため、DPI 対応のグラフィックスとテキストは大きくなります。DPI を大きくすると、特に高解像度の場合にはテキストが読みやすくなります。

すべてのアプリケーションが DPI に対応しているわけではありません。一部のアプリケーションでは、主要な測定単位としてハードウェア ピクセルが使用されているため、システム DPI を変更しても影響がありません。また、フォント サイズを表す場合は DPI 対応の単位を使用しても、それ以外にはすべてピクセルを使用するアプリケーションも数多くあります。これらのアプリケーションで DPI を過度に小さくしたり、大きくしたりすると、アプリケーションのテキストがシステムの DPI 設定に従ってスケーリングされても、アプリケーションの UI はスケーリングされないため、レイアウトの問題が発生する可能性があります。この問題は WPF を使用して開発されたアプリケーションでは発生しません。

WPF では、ハードウェア ピクセルの代わりにデバイス非依存ピクセルを主要測定単位として用いた自動拡大縮小機能がサポートされています。つまり、アプリケーション開発者が手を加えなくても、グラフィックスとテキストが適切に拡大縮小されます。次の図は WPF のテキストとグラフィックスが DPI が異なる場合にどのように表示されるかを示したものです。

さまざまな DPI 設定のグラフィックとテキスト

異なる DPI 設定のグラフィックスとテキスト

VisualTreeHelper クラス

VisualTreeHelper クラスは、ビジュアル オブジェクト レベルでの低レベルのプログラミング機能を提供する静的なヘルパ クラスです。このプログラミング機能は、高性能のカスタム コントロールの開発など、非常に限定されたシナリオで役立ちます。ほとんどの場合、より高レベルの WPFフレームワーク (CanvasTextBlock など) を使用することで、柔軟性と使いやすさが向上します。

ヒット テスト

VisualTreeHelper クラスは、ビジュアル オブジェクトに対するヒット テストのためのメソッドを提供します。既定のヒット テスト サポートが要件を満たさない場合は、これらのメソッドを使用できます。VisualTreeHelper クラスの HitTest メソッドを使用すると、ジオメトリまたはポイントの座標値が特定のオブジェクト (コントロールやグラフィック要素など) の境界内にあるかどうかを確認できます。たとえば、ヒット テストを使用することで、オブジェクトの外接する四角形内でのマウス クリックが円のジオメトリ内にあるかどうかを確認できます。また、ヒット テストの既定の実装をオーバーライドして、独自のカスタム ヒット テスト計算を実行することもできます。

ヒット テストの詳細については、「ビジュアル層でのヒット テスト」参照してください。

ビジュアル ツリーを列挙する

VisualTreeHelper クラスは、ビジュアル ツリーのメンバを列挙するための機能を提供します。親を取得するには、GetParent メソッドを呼び出します。ビジュアル オブジェクトの子または直接の子孫を取得するには、GetChild メソッドを呼び出します。このメソッドは、指定したインデックス位置にある親の子 Visual を返します。

ビジュアル オブジェクトのすべての子孫を列挙する方法を次の例に示します。これは、ビジュアル オブジェクト階層のすべての描画情報のシリアル化が必要である場合に使用できる手法です。

// Enumerate all the descendants of the visual object.
static public void EnumVisual(Visual myVisual)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
    {
        // Retrieve child visual at specified index value.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);

        // Do processing of the child visual object.

        // Enumerate children of the child visual object.
        EnumVisual(childVisual);
    }
}

ほとんどの場合、WPF アプリケーションの要素を表すときには論理ツリーの方が役立ちます。論理ツリーを直接変更することはありませんが、アプリケーションのこのビューは、プロパティの継承やイベントのルーティングを理解する上で役立ちます。ビジュアル ツリーとは異なり、論理ツリーは、ListItem などのビジュアル データ オブジェクト以外のオブジェクトを表すことができます。論理ツリーの詳細については、「WPF のツリー」を参照してください。

VisualTreeHelper クラスは、ビジュアル オブジェクトの外接する四角形を返すメソッドを提供します。GetContentBounds を呼び出すと、ビジュアル オブジェクトの外接する四角形が返されます。GetDescendantBounds を呼び出すと、ビジュアル オブジェクトのすべての子孫 (ビジュアル オブジェクト自体も含む) の外接する四角形が返されます。ビジュアル オブジェクトとそのすべての子孫の外接する四角形を計算する方法を次のコード例に示します。

// Return the bounding rectangle of the parent visual object and all of its descendants.
Rect rectBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);

参照

概念

パフォーマンスの最適化 : 2D グラフィックスとイメージング

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

DrawingVisual オブジェクトの使用

チュートリアル : Win32 アプリケーションでのビジュアル オブジェクトのホスト

WPF アプリケーションのパフォーマンスの最適化

参照

Visual

VisualTreeHelper

DrawingVisual