Graphics.CopyFromScreen是Windows Forms下最轻量、无需第三方库的截图方案,适用于单屏主显示器截图,核心是将屏幕像素拷贝到Bitmap并保存;需注意坐标原点为屏幕左上角、必须用Screen.PrimaryScreen.Bounds获取真实尺寸、在UI线程调用、多屏需显式指定Screen.AllScreens索引、后台服务不可用、保存时须显式指定ImageFormat.Png以支持透明和格式一致。

用 Graphics.CopyFromScreen 截当前屏幕最简单
这是 Windows Forms 下最轻量、无需第三方库的方案,适合单屏、主显示器截图。核心是把屏幕像素“拷”进 Bitmap,再保存。
常见错误是没指定正确的源坐标和尺寸,导致截出黑图或偏移。注意:原点 (0, 0) 是屏幕左上角,不是窗体左上角。
-
Graphics.CopyFromScreen第一、二个参数是屏幕 X/Y 起始坐标,第三、四个是目标矩形宽高,第五个是拷贝方式(一般用CopyPixelOperation.SourceCopy) - 要截全屏,宽高必须用
Screen.PrimaryScreen.Bounds.Width/Height,不能用窗体Size或ClientSize - 必须在 UI 线程调用(比如按钮点击事件里),否则可能抛
InvalidOperationException
var bounds = Screen.PrimaryScreen.Bounds;
using var bitmap = new Bitmap(bounds.Width, bounds.Height);
using var g = Graphics.FromImage(bitmap);
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("screenshot.png", ImageFormat.Png);
多显示器下用 Screen.AllScreens 明确指定目标屏
默认 PrimaryScreen 不一定是你想要的屏——尤其外接显示器时,主屏可能是笔记本内置屏。不显式选择,容易截错画面。
每个 Screen 对象含 Bounds(含任务栏)、WorkingArea(不含任务栏),按需选。索引从 0 开始,AllScreens[0] 不一定是主屏。
- 遍历
Screen.AllScreens可列出所有屏信息,用screen.DeviceName区分物理设备(如\.DISPLAY1) - 若要截第二块屏,直接用
Screen.AllScreens[1].Bounds,别硬算偏移 - 跨屏区域截图(比如横跨两屏)需手动拼接多个
Bitmap,CopyFromScreen不支持负坐标或超界矩形
后台服务或无窗口场景下 Graphics.CopyFromScreen 会失败
该方法依赖 GDI+ 的桌面设备上下文,Windows 服务、WPF 后台线程、或 Session 0 隔离环境下无法访问交互式桌面,会抛 ArgumentException 或返回黑图。
此时必须换方案:DesktopDuplication API(Win10+)或 PrintWindow(兼容性好但有闪烁风险)。前者需要 COM 初始化、DXGI 设置,后者需 P/Invoke 且对 UWP/某些全屏应用无效。
- 简单判断是否可用:调用前检查
SystemInformation.TerminalServerSession和当前线程是否在 STA - 若必须支持服务模式,优先考虑
DesktopDuplication,但要注意它不捕获光标,需额外绘制 -
PrintWindow方案中,目标窗口句柄传HWND_DESKTOP(IntPtr.Zero)可截桌面,但 Vista+ 后部分系统会限制权限
保存为图片时注意 ImageFormat 和文件后缀一致性
用 ImageFormat.Jpeg 保存但扩展名写 .png,不会报错,但生成的文件实际是 JPEG 流——用图像查看器可能打不开或显示异常。
更隐蔽的问题是 Alpha 通道:PNG 支持透明,JPEG 不支持。如果截图区域含半透明元素(如 Aero 毛玻璃),用 JPEG 保存会强制丢弃 Alpha,变成纯白背景。
- 推荐统一用
ImageFormat.Png,无损、支持透明、通用性强 - 若需压缩体积,改用
JpegEncoder并显式设置质量(Encoder.Quality参数),别只靠扩展名 - 路径含中文或空格时,确保目录已存在,
Save()不自动创建父目录
多屏、后台、格式这三处最容易掉坑——尤其是开发环境能跑,部署到服务器就黑屏,往往卡在 Session 隔离或格式误用上。











