最稳方法是用GetWindowDC(hWnd)+BitBlt截指定窗口,再经Gdiplus::Bitmap::Save保存;需确保GDI+初始化、正确传入编码器CLSID与EncoderParameters,且目标窗口可见、未挂起。

Windows 平台用 BitBlt + Gdiplus::Bitmap::Save 截指定窗口最稳
直接调 BitBlt 从窗口 DC 拷贝图像,比全屏抓取更可靠,尤其对 DWM 启用(Aero)或无边框窗口也有效。关键不是“能不能截”,而是“截到的是不是实际渲染内容”——很多程序用 DirectX 或 OpenGL 渲染,GDI 截图会空白,但普通 Win32 窗口、Qt、WPF(非硬件加速模式)基本没问题。
实操要点:
-
GetWindowDC(hWnd)比GetDC(hWnd)更稳妥,能捕获非客户区(标题栏、边框) - 必须用
CreateCompatibleBitmap配合目标 DC 创建位图,不能用屏幕 DC 创建后 BitBlt 到内存 DC——尺寸错位会导致黑块或偏移 - 调
Gdiplus::Bitmap::Save前需确保 GDI+ 已初始化(GdiplusStartup),且传入的编码器 CLSID 正确,例如 JPEG 对应CLSID_JPEGEncoder - 保存路径含中文时,
Bitmap::Save的LPCWSTR参数必须是 UTF-16,不能传std::string.c_str()
全屏截图用 GetDesktopWindow + GetWindowRect 获取真实分辨率
别直接用 GetSystemMetrics(SM_CXSCREEN),它返回的是虚拟屏幕宽度(多显示器时可能不准)。正确做法是获取桌面窗口句柄,再用 GetWindowRect 拿矩形区域——这样能兼容缩放(如 125% DPI)、多屏拼接、任务栏自动隐藏等状态。
常见错误:
- 用
GetDC(NULL)截全屏,结果只截了主屏,副屏内容丢弃 - 没调
SetStretchBltMode(hdcMem, HALFTONE)就缩放保存,JPEG 质量骤降、出现明显色块 - 保存为 PNG 时未设置
EncoderQuality参数,默认是 75,但 PNG 不需要质量参数,强行设会导致保存失败(返回GenericError)
压缩控制靠 EncoderParameters,不是文件后缀名
后缀名只是提示,真正决定压缩率的是 Gdiplus::EncoderParameters 结构体。JPEG 用 EncoderQuality(0–100),PNG 不支持该参数,WebP 才用 EncoderCompression 和 EncoderQuality 双控。
示例关键片段(JPEG 压缩):
GUID guid = EncoderQuality; EncoderParameters encoderParams; encoderParams.Count = 1; encoderParams.Parameter[0].Guid = guid; encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong; encoderParams.Parameter[0].NumberOfValues = 1; encoderParams.Parameter[0].Value = &quality; // quality = 85 bmp->Save(L"out.jpg", &clsid, &encoderParams);
注意:quality 是 ULONG 类型,不是 int;传地址前必须确保变量生命周期覆盖 Save 调用。
跨进程窗口截图要处理权限和可见性
比如截微信主窗口(weixinApp 类名),若其处于最小化或被其他窗口完全遮挡,BitBlt 仍能拿到图像(因为窗口 DC 一直存在),但若对方进程已挂起或 UI 线程卡死,GetWindowDC 可能返回 NULL 或截到旧帧。
安全做法:
- 先
IsWindowVisible(hWnd)和IsIconic(hWnd)判断状态,避免白图 - 对关键窗口(如游戏、远程桌面客户端),加
SendMessageTimeout发WM_PAINT触发重绘,再延时 10ms 再截 - 不要用
FindWindow硬编码类名,改用EnumWindows+GetClassName动态匹配,防版本更新改类名
真正难的不是 API 调用,是判断“此刻这个窗口到底有没有可截图的有效画面”——它取决于目标进程是否响应、DWM 是否启用、是否用了 DXGI Desktop Duplication(那种就得换方案了)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











