C++中如何将Gdiplus::Image设置为HDC/HWND当前显示的截图内容
实现方案
前置条件
使用前请确保项目已正确初始化GDI+,初始化示例代码如下:
// 全局变量 ULONG_PTR gdiplusToken; // 程序入口处初始化 Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // 程序退出前释放 Gdiplus::GdiplusShutdown(gdiplusToken);
从HWND窗口句柄生成Gdiplus::Image
以下代码可直接截取指定窗口的客户区或全窗口内容,生成GDI+图像对象:
#include <gdiplus.h> #pragma comment(lib, "gdiplus.lib") /** * @param hWnd 目标窗口句柄 * @param bCaptureFullWindow 为TRUE时截取包括标题栏、边框的全窗口,为FALSE时仅截取客户区 * @return 返回Gdiplus::Bitmap指针,可直接转为Gdiplus::Image*使用,使用完成后需手动delete释放 */ Gdiplus::Bitmap* HwndToImage(HWND hWnd, BOOL bCaptureFullWindow = FALSE) { // 获取窗口对应的DC HDC hWndDC = bCaptureFullWindow ? GetWindowDC(hWnd) : GetDC(hWnd); // 获取窗口尺寸 RECT rc; bCaptureFullWindow ? GetWindowRect(hWnd, &rc) : GetClientRect(hWnd, &rc); int width = rc.right - rc.left; int height = rc.bottom - rc.top; // 创建兼容内存DC和兼容位图 HDC hMemDC = CreateCompatibleDC(hWndDC); HBITMAP hBmp = CreateCompatibleBitmap(hWndDC, width, height); HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp); // 拷贝窗口内容到内存位图 // 若窗口被遮挡/最小化时需要截图,请将下行替换为 PrintWindow(hWnd, hMemDC, bCaptureFullWindow ? 0 : PW_CLIENTONLY); BitBlt(hMemDC, 0, 0, width, height, hWndDC, 0, 0, SRCCOPY); // 将HBITMAP转为GDI+ Bitmap对象 Gdiplus::Bitmap* pImage = new Gdiplus::Bitmap(hBmp, NULL); // 释放GDI资源 SelectObject(hMemDC, hOldBmp); DeleteObject(hBmp); DeleteDC(hMemDC); ReleaseDC(hWnd, hWndDC); return pImage; }
从现有HDC设备上下文生成Gdiplus::Image
如果已经持有目标区域的HDC,可直接使用以下方法生成图像:
/** * @param hSrcDC 源设备上下文句柄 * @param width 要截取的区域宽度 * @param height 要截取的区域高度 * @return 返回Gdiplus::Bitmap指针,可直接转为Gdiplus::Image*使用,使用完成后需手动delete释放 */ Gdiplus::Bitmap* HdcToImage(HDC hSrcDC, int width, int height) { HDC hMemDC = CreateCompatibleDC(hSrcDC); HBITMAP hBmp = CreateCompatibleBitmap(hSrcDC, width, height); HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp); BitBlt(hMemDC, 0, 0, width, height, hSrcDC, 0, 0, SRCCOPY); Gdiplus::Bitmap* pImage = new Gdiplus::Bitmap(hBmp, NULL); SelectObject(hMemDC, hOldBmp); DeleteObject(hBmp); DeleteDC(hMemDC); return pImage; }
常见问题排查
- 生成的图像全黑:请检查是否用源HDC(而非内存DC)创建兼容位图,是否完成GDI+初始化。
- 窗口被遮挡/最小化时截图黑屏:将
BitBlt替换为PrintWindow接口即可适配该场景。 - 资源泄露:返回的
Gdiplus::Image对象使用完成后必须手动调用delete释放,GDI+对象不会自动回收资源。
内容的提问来源于stack exchange,提问作者Itzsten
相关产品推荐
相关产品推荐

