方法 : CompositionTarget を使用したフレームの間隔ごとの描画
WPF のアニメーション エンジンには、フレームベースのアニメーションを作成するためのさまざまな機能が用意されています。 ただし、フレームベースの描画をさらにきめ細かく制御することが必要となるアプリケーション シナリオがあります。 CompositionTarget オブジェクトを使用すると、フレームごとのコールバックに基づいてカスタム アニメーションを作成できます。
CompositionTarget は、アプリケーションが描画される表示サーフェイスを表す静的クラスです。 アプリケーションのシーンが描画されるたびに Rendering イベントが発生します。 レンダリング フレーム レートは、1 秒あたりのシーンの描画回数です。
![]() |
---|
CompositionTarget を使用したコード サンプル全体については、「Using the CompositionTarget Sample (CompositionTarget のサンプルの使用)」を参照してください。 |
使用例
Rendering イベントは、WPF の描画プロセス中に発生します。 静的 Rendering メソッドに対する EventHandler デリゲートを CompositionTarget に登録する方法を次の例に示します。
' Add an event handler to update canvas background color just before it is rendered.
AddHandler CompositionTarget.Rendering, AddressOf UpdateColor
// Add an event handler to update canvas background color just before it is rendered.
CompositionTarget.Rendering += UpdateColor;
独自の描画イベント ハンドラー メソッドを使用して、描画のカスタム コンテンツを作成できます。 このイベント ハンドラー メソッドは、フレームごとに 1 回呼び出されます。 WPF がビジュアル ツリーの永続化されたレンダリング データを合成シーン グラフにマーシャリングするたびに、イベント ハンドラー メソッドが呼び出されます。 さらに、ビジュアル ツリーに対する変更によって合成シーン グラフが強制的に更新される場合も、イベント ハンドラー メソッドが呼び出されます。 イベント ハンドラー メソッドは、レイアウトが計算された後に呼び出されます。 ただし、イベント ハンドラー メソッド内でレイアウトを変更できます。つまり、そのレイアウトは、描画する前にもう一度計算されることになります。
CompositionTarget イベント ハンドラー メソッドでカスタム描画を指定する方法を次の例に示します。 この場合、Canvas の背景色は、マウスの座標位置に基づくカラー値で描画されます。 Canvas 内でマウスを移動すると、その背景色が変わります。 また、現在の経過時間および描画されたフレームの合計数に基づいて、平均フレーム レートが計算されます。
' Called just before frame is rendered to allow custom drawing.
Protected Sub UpdateColor(ByVal sender As Object, ByVal e As EventArgs)
If _frameCounter = 0 Then
' Starting timing.
_stopwatch.Start()
End If
_frameCounter = _frameCounter + 1
' Determine frame rate in fps (frames per second).
Dim frameRate As Long = CLng(Fix(_frameCounter / Me._stopwatch.Elapsed.TotalSeconds))
If frameRate > 0 Then
' Update elapsed time, number of frames, and frame rate.
myStopwatchLabel.Content = _stopwatch.Elapsed.ToString()
myFrameCounterLabel.Content = _frameCounter.ToString()
myFrameRateLabel.Content = frameRate.ToString()
End If
' Update the background of the canvas by converting MouseMove info to RGB info.
Dim redColor As Byte = CByte(_pt.X / 3.0)
Dim blueColor As Byte = CByte(_pt.Y / 2.0)
myCanvas.Background = New SolidColorBrush(Color.FromRgb(redColor, &H0, blueColor))
End Sub
// Called just before frame is rendered to allow custom drawing.
protected void UpdateColor(object sender, EventArgs e)
{
if (_frameCounter++ == 0)
{
// Starting timing.
_stopwatch.Start();
}
// Determine frame rate in fps (frames per second).
long frameRate = (long)(_frameCounter / this._stopwatch.Elapsed.TotalSeconds);
if (frameRate > 0)
{
// Update elapsed time, number of frames, and frame rate.
myStopwatchLabel.Content = _stopwatch.Elapsed.ToString();
myFrameCounterLabel.Content = _frameCounter.ToString();
myFrameRateLabel.Content = frameRate.ToString();
}
// Update the background of the canvas by converting MouseMove info to RGB info.
byte redColor = (byte)(_pt.X / 3.0);
byte blueColor = (byte)(_pt.Y / 2.0);
myCanvas.Background = new SolidColorBrush(Color.FromRgb(redColor, 0x0, blueColor));
}
カスタム描画は、コンピューターごとに異なる速度で実行される場合があります。 これは、カスタム描画がフレーム レートに依存するためです。 実行しているシステムとそのシステムの負荷に応じて、Rendering イベントが 1 秒あたりに呼び出される回数が異なる場合があります。 WPF アプリケーションを実行するデバイスのグラフィックス ハードウェアの機能およびパフォーマンスの決定については、「グラフィックスの描画層」を参照してください。
イベントの発生中の描画 EventHandler デリゲートの追加または削除は、イベントが終了するまで遅延します。 これは、MulticastDelegate ベースのイベントが共通言語ランタイム (CLR) で処理される方法と一貫性があります。 また、描画イベントが特定の順序で呼び出されるかどうかは保証されません。 特定の順序に依存する複数の EventHandler デリゲートがある場合、単一の Rendering イベントを登録し、手動でデリゲートを正しい順序で多重化する必要があります。