首先(这与您的主要问题无关):
创建屏幕截图位图时,不要使用内存 dc,因为这会创建单色位图。这是您获得黑白图像的主要原因(在我的计算机上我只获得黑色图像)。
不要使用GetDC(0)
在另一个函数内。每次致电GetDC
匹配 有一个匹配ReleaseDC
以避免资源泄漏。
打电话后BitBlt
这是一个很好的选择hbitmap
out of dc
因为你基本上已经在dc上画完了。
以下代码适用于 Windows 10
int w = 800;
int h = 600;
HDC hdc = GetDC(HWND_DESKTOP);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, w, h);
HBITMAP oldbmp = (HBITMAP)SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, w, h, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
SelectObject(memdc, oldbmp);
Bitmap(hbitmap, NULL).Save(filename, &pngEncoder);
DeleteObject(hbitmap);
DeleteDC(memdc);
ReleaseDC(HWND_DESKTOP, hdc);
回到您有关文档的问题:
类型:HPALETTE
如果 hbm 不是设备无关位图 (DIB),则用于定义位图颜色的 GDI 调色板的句柄。
此外,
不要将当前(或之前)选择到设备上下文中的 GDI 位图或 GDI 调色板传递给 Bitmap::FromHBITMAP 方法。
我发布的代码仅遵循一条规则,即当前未将 GDI 位图选择到设备上下文中(但之前已选择过)。
该文档可能适用于旧版本的 Windows。据我所知 MFCCImage
类不遵循所有这些规则。新的计算机显示器都是 24 或 32 位的,我不知道你如何获得它的调色板。
要严格遵循文档,您可以将 DDB 转换为 DIB 部分,使用CreateDIBSection
and GetDIBits
。使用新的 DIB 部分hbitmap_dib
in Bitmap::FromHBITMAP
。这将满足所有条件:hbitmap
是 dib,它没有(也没有)被选择到设备上下文中。
Or, Gdiplus::Bitmap
还有另一种方法Bitmap::FromBITMAPINFO
。如果没有调色板,您可以使用以下代码代替:
HDC hdc = GetDC(HWND_DESKTOP);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, w, h);
HBITMAP oldbmp = (HBITMAP)SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, 800, 600, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
SelectObject(memdc, oldbmp);
BITMAP bm;
GetObject(hbitmap, sizeof(bm), &bm);
int size = ((bm.bmWidth * bm.bmBitsPixel + 31) / 32) * 4 * bm.bmHeight;
BITMAPINFO info{ sizeof(info), bm.bmWidth, bm.bmHeight, 1, bm.bmBitsPixel, BI_RGB, size };
std::vector<char> bits(size);
GetDIBits(memdc, hbitmap, 0, bm.bmHeight, &bits[0], &info, DIB_RGB_COLORS);
Bitmap *bitmap = Bitmap::FromBITMAPINFO(&info, &bits[0]);
bitmap->Save(filename, &pngEncoder);
delete bitmap;
DeleteObject(hbitmap);
DeleteDC(memdc);
ReleaseDC(HWND_DESKTOP, hdc);