共计 1447 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
在开发需要屏幕录制功能的 C# 应用时,很多开发者会遇到以下典型问题:

- 直接使用 DirectX 或 Windows.Graphics.Capture 需要处理复杂的 API 和权限问题
- 跨 Windows 版本兼容性差,特别是企业环境中老系统占比高
- 自行实现帧捕获和编码会导致较高的 CPU 和内存占用
- 杀毒软件容易误拦截录屏行为
技术选型对比
- DirectX 方式
- 优点:性能最好,延迟最低
-
缺点:代码复杂度高,需要处理 DXGI 适配器选择
-
Windows.Graphics.Capture
- 优点:Win10 1803+ 原生支持
-
缺点:需要处理 UWP 权限弹窗
-
调用系统截图工具
- 优点:兼容性好(Win7+),系统级稳定性
- 缺点:帧率受限(约 30FPS)
核心实现步骤
1. P/Invoke 关键 API 准备
[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();
[DllImport("gdi32.dll")]
static extern bool BitBlt(
IntPtr hdcDest, int xDest, int yDest,
int wDest, int hDest,
IntPtr hdcSrc, int xSrc, int ySrc,
CopyPixelOperation rop);
2. 帧捕获流程
- 创建兼容 DC
- 按设定间隔捕获屏幕
- 将位图存入内存队列
3. 视频编码处理
- 使用 MediaFoundation 或 FFmpeg 进行 H264 编码
- 建议单独线程处理编码避免阻塞采集
完整代码实现
public class ScreenRecorder
{
private readonly int _fps;
private bool _isRecording;
public ScreenRecorder(int fps = 30)
{_fps = fps;}
public void Start(string outputPath)
{
_isRecording = true;
Task.Run(() => RecordLoop(outputPath));
}
private void RecordLoop(string path)
{using var writer = new VideoFileWriter();
// 初始化编码器...
while(_isRecording)
{var frame = CaptureFrame();
writer.WriteFrame(frame);
Thread.Sleep(1000 / _fps);
}
}
private Bitmap CaptureFrame()
{// 具体捕获实现...}
}
生产环境优化
多显示器处理
var allScreens = Screen.AllScreens;
var totalWidth = allScreens.Sum(s => s.Bounds.Width);
var maxHeight = allScreens.Max(s => s.Bounds.Height);
内存管理要点
- 复用 Bitmap 对象避免频繁 GC
- 使用对象池管理帧缓冲区
- 设置合理的队列长度防止内存暴涨
常见问题解决方案
- DPI 缩放问题
- 调用 SetProcessDPIAware
-
手动计算缩放比例
-
权限被拒绝
- 添加 app.manifest 要求 uiAccess
-
对于企业应用使用证书签名
-
杀毒软件拦截
- 提前将程序加入白名单
- 使用合法数字签名
扩展思考
当前方案完全依赖 CPU 处理,对于需要更高性能的场景,可以考虑:
- 通过 Direct3D11 实现硬件加速
- 使用 NVENC 等专用编码芯片
- 多线程并行处理不同屏幕区域
期待看到大家对这些扩展方向的实践分享!
正文完
