能否为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
相关产品推荐
相关产品推荐

