WPFのRenderingイベントでFPSを表示するサンプルコード

コンピュータ

WPFのWinodwオブジェクトのRenderingイベント(CompositionTarget.Rendering)を使うと、描画のタイミングで処理が実行されます。
ディスプレイの処理能力次第なのですが、一般的なのPCだと60FPSぐらいになると思われますので、サンプルコードで確認したいと思います。

ソースコード

ファイル名:RenderEventSample.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:MainWindow.xaml.cs

using System.Windows;
using System.Windows.Media;

namespace RenderEventSample;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    long lastTime = 0;
    double fps = 0;

    public MainWindow()
    {
        InitializeComponent();

        // Renderingイベント登録
        CompositionTarget.Rendering += OnRendering;

        lastTime = DateTime.Now.Ticks;
    }
    void OnRendering(object? sender, EventArgs e)
    {
        long now = DateTime.Now.Ticks;
        double dt = (now - lastTime) / 10_000_000.0; // 秒
        lastTime = now;

        // FPS計算
        if (dt > 0)
            fps = 1.0 / dt;

        // 画面表示
        FpsText.Text = $"FPS: {fps:0.0}";
    }
}

実行

実行すると、ウィンドウをが表示され、黒背景に緑色の文字列でFPSが表示されます。
手元の実行環境では60FPS前後の数値が出ていますが、少しばらつくようです。

感想

アニメーションやゲームを為のループを処理を書く場合Timer系を使うより、レンダリングのタイミングで実行されるCompositionTarget.Renderingの方が向いている感じがします。
ただWindowsのイベントですので精度はそれなりですし、WPFで扱う領域でも無さそうですが、覚えておくと使える場面がありそうですね。

コメント