You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否为C#程序实现FPS计数器?Overlay方案全部失效求助

C# Overlay目标窗口FPS计数器实现方案

现有代码基础

已实现目标窗口查找与Overlay置顶功能,代码如下:

private IntPtr FindTargetWindow(string windowTitle)
{
    IntPtr targetHandle = IntPtr.Zero;
    foreach (var process in Process.GetProcesses())
    {
        if (process.MainWindowTitle.Contains(windowTitle))
        {
            targetHandle = process.MainWindowHandle;
            break;
        }
    }
    return targetHandle;
}

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    targetWindowHandle = FindTargetWindow("MinutesTillDawn");

    this.Topmost = true;

    updateTimer.Start();

}

实现FPS计数器的完整方案

1. 核心FPS统计逻辑

通过Stopwatch统计固定时间内的渲染帧数,结合DispatcherTimer每秒更新显示:

首先定义所需变量:

private int _frameCount;
private Stopwatch _stopwatch;
private DispatcherTimer _fpsUpdateTimer;
private Label _fpsDisplayLabel; // 替换为你Overlay中用于显示FPS的Label控件

在OnSourceInitialized中初始化FPS相关组件:

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    targetWindowHandle = FindTargetWindow("MinutesTillDawn");
    this.Topmost = true;

    // 初始化FPS统计
    _stopwatch = Stopwatch.StartNew();
    _fpsUpdateTimer = new DispatcherTimer
    {
        Interval = TimeSpan.FromSeconds(1) // 每秒更新一次FPS数值
    };
    _fpsUpdateTimer.Tick += FpsUpdateTimer_Tick;
    _fpsUpdateTimer.Start();

    // 绑定渲染事件统计帧数
    CompositionTarget.Rendering += CompositionTarget_Rendering;

    updateTimer.Start();
}

实现计时器回调与渲染计数:

private void CompositionTarget_Rendering(object sender, EventArgs e)
{
    // 每完成一帧渲染,计数加1
    _frameCount++;
}

private void FpsUpdateTimer_Tick(object sender, EventArgs e)
{
    // 计算当前FPS
    double currentFps = _frameCount / _stopwatch.Elapsed.TotalSeconds;
    // 更新Label显示,保留1位小数
    _fpsDisplayLabel.Content = $"FPS: {currentFps:F1}";

    // 重置计数与计时器,准备下一轮统计
    _frameCount = 0;
    _stopwatch.Restart();
}

2. 优化Overlay跟随逻辑

为确保Overlay完全贴合目标窗口,在updateTimer的回调中同步窗口位置与尺寸,需引入Windows API:

private void UpdateTimer_Tick(object sender, EventArgs e)
{
    if (targetWindowHandle == IntPtr.Zero) return;

    if (GetWindowRect(targetWindowHandle, out RECT targetRect))
    {
        // 同步Overlay与目标窗口的位置和大小
        this.Left = targetRect.Left;
        this.Top = targetRect.Top;
        this.Width = targetRect.Right - targetRect.Left;
        this.Height = targetRect.Bottom - targetRect.Top;
    }
}

// 导入Windows API所需结构与方法
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

3. 关键配置与注意事项

  • Overlay窗口需设置为无边框透明样式,避免干扰目标窗口操作:
    <!-- 在XAML中配置窗口属性 -->
    <Window WindowStyle="None" AllowsTransparency="True" Background="Transparent" />
    
  • 若需要统计目标进程的FPS(而非Overlay自身),可使用PerformanceCounter:
    private PerformanceCounter _targetFpsCounter;
    
    // 初始化(需确保目标进程已启动)
    var targetProcess = Process.GetProcessesByName("MinutesTillDawn").FirstOrDefault();
    if (targetProcess != null)
    {
        _targetFpsCounter = new PerformanceCounter("Process", "Elapsed Time", targetProcess.ProcessName);
    }
    
    // 在计时器中获取目标FPS
    double targetFps = 1000 / _targetFpsCounter.NextValue();
    

内容的提问来源于stack exchange,提问作者louie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:45:33