能,但必须满足三个硬条件:目标Bitmap已创建且尺寸匹配、源坐标是物理屏幕坐标、调用线程不能是目标窗口的UI线程;常见错误包括硬编码分辨率、忽略DPI感知、未释放GDI句柄、遗漏鼠标绘制及错误保存格式。

Graphics.CopyFromScreen 能不能直接用?
能,但必须满足三个硬条件:目标 Bitmap 已创建且尺寸匹配、源坐标是物理屏幕坐标、调用线程不能是目标窗口的 UI 线程。
常见错误是写成 new Bitmap(1920, 1080) 硬编码分辨率——多屏或任务栏在顶部时,实际可用区域远小于此;应始终用 Screen.PrimaryScreen.Bounds 或 Screen.FromPoint(Cursor.Position).Bounds 动态获取。CopyFromScreen 第 1–2 个参数是源左上角屏幕坐标(不是窗体客户区),第 3–4 个是目标位图内偏移(通常为 Point.Empty)。
不加 using (var g = Graphics.FromImage(bitmap)) 包裹会导致 GDI 句柄泄漏,进程跑久后截图会突然失败并抛 OutOfMemoryException。
为什么截图里没有鼠标?怎么补上?
因为 Windows 将鼠标指针渲染在独立的硬件叠加层(cursor overlay),CopyFromScreen 读的是显存中合成后的桌面图像,根本看不到指针。
要加上,得手动做三件事:
- 用 P/Invoke 调
User32.GetCursorInfo拿到当前光标句柄、位置和可见状态 - 用
Icon.FromHandle把HCURSOR转成Icon - 在截图
Bitmap上用Graphics.DrawIcon绘制,注意高 DPI 下需换算:若GetCursorInfo.ptScreenPos返回物理坐标,而你的Bitmap是逻辑尺寸,就得用g.DpiX/g.DpiY缩放光标位置
跳过这步,用户第一反应就是“鼠标哪去了”,而不是去查文档。
高 DPI 屏幕下截图偏移或变模糊怎么办?
根本原因是逻辑像素和物理像素混淆。比如缩放设为 125%,Screen.PrimaryScreen.Bounds.Width 返回的是逻辑宽度(如 1536),但 CopyFromScreen 按物理像素操作(实际是 1920)。
解决方案有两个:
- 启用 Per-Monitor DPI 感知:在
app.manifest中添加dpiAwareness="PerMonitorV2",并在程序启动时调用SetProcessDpiAwarenessContext(.NET 5+)或SetProcessDPIAware(旧版) - 或者绕过 DPI 换算:改用
Graphics.CopyFromScreen(Point, Point, Size, CopyPixelOperation.SourceCopy)重载,并确保传入的Size是物理尺寸
不处理 DPI,截出来的图要么缺一块,要么被拉伸糊掉,尤其在双屏不同缩放率时更明显。
保存文件时为什么图片巨大或透明变白?
Bitmap.Save("a.jpg") 默认保存为无压缩 BMP 格式,哪怕扩展名是 .jpg——文件体积可能是 PNG 的 5–10 倍。
更隐蔽的问题是 Alpha 通道:如果截图含半透明窗体(如 UWP 或启用了 WS_EX_LAYERED 的窗口),用 JPEG 保存会强制丢弃透明度,变成白底;必须用 ImageFormat.Png。
另外,建议保存前调用 bitmap.SetResolution(96, 96),否则某些查看器会按默认 96dpi 渲染,导致显示过小。
别依赖扩展名判断格式,Save 的第二个参数才是真实编码器。










