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で扱う領域でも無さそうですが、覚えておくと使える場面がありそうですね。

コメント