次の方法で共有


方法: CompositionTarget を使用してフレームごとの間隔でレンダリングする

WPF アニメーション エンジンには、フレーム ベースのアニメーションを作成するための多くの機能が用意されています。 ただし、フレームごとにレンダリングをきめ細かく制御する必要があるアプリケーション シナリオがあります。 CompositionTarget オブジェクトは、フレームごとのコールバックに基づいてカスタム アニメーションを作成する機能を提供します。

CompositionTarget は、アプリケーションが描画されている表示サーフェイスを表す静的クラスです。 Rendering イベントは、アプリケーションのシーンが描画されるたびに発生します。 レンダリング フレーム レートは、シーンが 1 秒あたりに描画される回数です。

手記

CompositionTargetを使用した完全なコード サンプルについては、「Using the CompositionTarget Sample」を参照してください。

Rendering イベントは、WPF レンダリング プロセス中に発生します。 次の例は、CompositionTargetの静的 Rendering メソッドに EventHandler デリゲートを登録する方法を示しています。

// Add an event handler to update canvas background color just before it is rendered.
CompositionTarget.Rendering += UpdateColor;
' Add an event handler to update canvas background color just before it is rendered.
AddHandler CompositionTarget.Rendering, AddressOf UpdateColor

レンダリング イベント ハンドラー メソッドを使用して、カスタム描画コンテンツを作成できます。 このイベント ハンドラー メソッドは、フレームごとに 1 回呼び出されます。 WPF がビジュアル ツリー内の永続化されたレンダリング データをコンポジション シーン グラフにマーシャリングするたびに、イベント ハンドラー メソッドが呼び出されます。 さらに、ビジュアル ツリーに対する変更によってコンポジション シーン グラフが強制的に更新されると、イベント ハンドラー メソッドも呼び出されます。 イベント ハンドラー メソッドは、レイアウトの計算後に呼び出されることに注意してください。 ただし、イベント ハンドラー メソッドではレイアウトを変更できます。つまり、レイアウトはレンダリングの前にもう一度計算されます。

次の例は、CompositionTarget イベント ハンドラー メソッドでカスタム描画を提供する方法を示しています。 この場合、Canvas の背景色は、マウスの座標位置に基づいて色の値で描画されます。 Canvas内でマウスを動かすと、背景色が変わります。 さらに、現在の経過時間とレンダリングされたフレームの合計数に基づいて、平均フレーム レートが計算されます。

// 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));
}
' 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

カスタム図面は、異なるコンピューター上で異なる速度で実行されている場合があります。 これは、カスタム図面がフレーム レートに依存しないためです。 実行しているシステムとそのシステムのワークロードによっては、Rendering イベントは 1 秒あたりに異なる回数呼び出される場合があります。 WPF アプリケーションを実行するデバイスのグラフィックス ハードウェアの機能とパフォーマンスの決定については、「Graphics Rendering Tiers」を参照してください。

イベントの発生中にレンダリング EventHandler デリゲートを追加または削除すると、イベントの発生が完了するまで遅延します。 これは、共通言語ランタイム (CLR) での MulticastDelegateベースのイベントの処理方法と一致します。 また、レンダリング イベントが特定の順序で呼び出されるとは限りません。 特定の順序に依存する複数の EventHandler デリゲートがある場合は、1 つの Rendering イベントを登録し、デリゲートを正しい順序で多重化する必要があります。

関連項目