共计 2062 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在开发需要录屏功能的应用时,很多 C# 开发者首先想到的是第三方库,比如 OpenCV、FFmpeg 等。但这些方案往往存在几个明显的问题:

- 依赖重:需要打包大量 DLL 文件,显著增加应用体积
- 授权复杂:某些库存在 GPL 协议风险
- 性能开销:跨语言调用导致帧率不稳定
- 兼容性问题:在不同 Windows 版本表现不一致
技术方案对比
Windows 平台其实提供了多种原生录屏方案,这里简单对比三种主流方案:
- Windows.Graphics.Capture API(推荐)
- 优点:系统原生支持,内存占用低,支持 DX12 纹理
-
缺点:仅限 Win10 1809+ 版本
-
DirectX 抓取
- 优点:高性能,可获取原始纹理
-
缺点:实现复杂,需要处理 DX 资源管理
-
FFmpeg+gdigrab
- 优点:跨平台兼容
- 缺点:CPU 占用高,延迟明显
核心实现步骤
1. 准备工作
首先确保项目满足以下条件:
- 目标平台设置为 x64
- 启用不安全代码(项目属性 > 生成)
- 添加 NuGet 包:Microsoft.Windows.SDK.Contracts
2. 声明 P /Invoke
[DllImport("windows.graphics.capture.dll")]
private static extern IntPtr CreateCaptureItemForWindow(
IntPtr window,
ref Guid iid);
[DllImport("d3d11.dll")]
private static extern int D3D11CreateDevice(
IntPtr adapter,
int driverType,
IntPtr software,
uint flags,
IntPtr featureLevels,
uint featureLevelsCount,
uint sdkVersion,
out IntPtr device,
out IntPtr featureLevel,
out IntPtr immediateContext);
3. 权限检查
if (!GraphicsCaptureSession.IsSupported())
{throw new NotSupportedException("当前系统版本不支持 GraphicsCapture");
}
完整代码实现
下面是核心录制类的实现(带关键注释):
public class ScreenRecorder : IDisposable
{
// 建议帧率范围:30-60
private const int TargetFrameRate = 60;
private GraphicsCaptureItem _captureItem;
private Direct3D11CaptureFramePool _framePool;
private GraphicsCaptureSession _session;
public async Task StartCaptureAsync(IntPtr hwnd)
{
// 创建 DX11 设备
D3D11CreateDevice(...);
// 初始化帧池
_framePool = Direct3D11CaptureFramePool.Create(
device,
DirectXPixelFormat.B8G8R8A8UIntNormalized,
2, // 缓冲帧数
_captureItem.Size);
// 帧到达事件处理
_framePool.FrameArrived += (s, e) =>
{using (var frame = _framePool.TryGetNextFrame())
{// 处理帧数据...}
};
// 开始录制
_session = _framePool.CreateCaptureSession(_captureItem);
_session.StartCapture();}
public void Dispose()
{_session?.Dispose();
_framePool?.Dispose();}
}
性能优化技巧
- 内存复用策略
- 重用 DX11 纹理资源
-
实现 IDisposable 及时释放非托管资源
-
线程模型选择
- UI 操作必须在主线程
-
帧处理建议用 ThreadPool
-
帧率控制
- 根据内容类型动态调整:
- 静态内容:30fps
- 游戏 / 视频:60fps
生产环境避坑指南
- UWP 权限问题
- 需要在 Package.appxmanifest 声明
screenCapture能力 -
对于桌面程序,需调用
Windows.Graphics.Capture.GraphicsCaptureAccess.RequestAccessAsync() -
多显示器适配
- 使用
DisplayMonitor类获取所有显示器信息 -
捕获特定显示器时需指定 RECT 区域
-
内存泄漏排查
- 确保所有 IDisposable 对象都被释放
- 使用 DX 调试层检查资源泄漏
延伸思考
掌握了基础录屏功能后,可以尝试以下进阶方向:
- 添加音频采集(通过 WASAPI)
- 支持 HDR 内容捕获
- 实现鼠标高亮效果
- 添加实时标注功能
参考资料
希望这篇指南能帮助你避开我踩过的那些坑。如果遇到任何问题,欢迎在评论区交流讨论!
正文完
