GetDIBits()を使う、以上。
で終わる話なのですが、BITMAPINFOを作成するために必要なメモリサイズを算出するのに手こずったので、結果だけ置いておきます。
なお、このコードで作成されるのは、スクリーンショットを撮ったときに得られるビットマップデータに合わせてbiCompressionがBI_BITFIELDSで、カラーマスクあり、カラーパレットなしの32ビットカラーDIBビットマップです。
BITMAPINFO* createBitmapInfo(HBITMAP hBitmap)
{
BITMAP bitmap;
GetObject(hBitmap, BITMAP.sizeof, &bitmap);
HDC hdc = GetDC(null);
// Allocates memory of BITMAPINFO
const uint bitsPerPixel = bitmap.bmPlanes * 32; // 32 bits color
const uint colorMaskBytes = {
// Contains color mask when biCompression is BI_BITFIELDS.
return 4 * 3; // 4 bytes * 3 masks(R,G,B)
}();
const uint numPallet = 0; // Wants that no color palette.
const uint widthBytes = (bitmap.bmWidth * bitsPerPixel + 31) / 32 * 4;
const uint bitmapBodySize = widthBytes * bitmap.bmHeight;
BITMAPINFO* pbi = cast(BITMAPINFO*)new ubyte[
BITMAPINFOHEADER.sizeof + colorMaskBytes + RGBQUAD.sizeof * numPallet + bitmapBodySize];
pbi.bmiHeader.biSize = BITMAPINFOHEADER.sizeof; // First 6 members
pbi.bmiHeader.biWidth = bitmap.bmWidth;
pbi.bmiHeader.biHeight = bitmap.bmHeight;
pbi.bmiHeader.biPlanes = bitmap.bmPlanes;
pbi.bmiHeader.biBitCount = 32; // 32 bits color
pbi.bmiHeader.biCompression = BI_BITFIELDS; // Contains color mask
if (0 == core.sys.windows.wingdi.GetDIBits(
hdc, hBitmap, 0, bitmap.bmHeight,
cast(ubyte*)pbi + BITMAPINFOHEADER.sizeof + colorMaskBytes + RGBQUAD.sizeof * numPallet, pbi, DIB_RGB_COLORS))
{
throw new Exception("createBitmapInfo failure");
}
ReleaseDC(null, hdc);
return pbi;
}