根据关于GDI函数RealizePalette()的MSDN文档:
RealizePalette 功能可修改设备的调色板 与指定的设备上下文相关联。 如果设备上下文是 存储器DC,选择到DC的位图的颜色表是 修改。
以斜体描述的行为似乎不适用于以下代码:
void test_color_tbl_modify(HWND hWnd) {
// initialize BITMAPINFO struct for a mono bitmap(red&white)
const int bmp_w = 16, bmp_h = 32;
std::vector<BYTE> vBytes(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 2); // for mono bitmaps, bmiColors member of BITMAPINFO contains two RGBQUAD elems
BITMAPINFO* pbmi = reinterpret_cast<BITMAPINFO*>(vBytes.data());
{
BITMAPINFOHEADER bih{};
{
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = bmp_w;
bih.biHeight = bmp_h;
bih.biPlanes = 1;
bih.biBitCount = 1;
bih.biCompression = BI_RGB;
bih.biSizeImage = ((bih.biWidth * bih.biBitCount + 31) & ~31) / 8 // each scanline aligned on DWORD boundary
* bih.biHeight;
bih.biClrUsed = 2;
bih.biClrImportant = 0;
}
pbmi->bmiHeader = bih;
pbmi->bmiColors[0] = RGBQUAD{0,0,255,0}; // red
pbmi->bmiColors[1] = RGBQUAD{255,255,255,0}; // white
}
// create a mono DDB
HDC hdc = GetDC(hWnd);
HDC hdcmem = CreateCompatibleDC(hdc); // has 1x1 mono bitmap selected into it by default
HBITMAP hbitmap = CreateCompatibleBitmap(hdcmem, bmp_w, bmp_h); // creates a mono-bitmap(see above)
// draw something
HGDIOBJ hOldBmp = SelectObject(hdcmem, hbitmap);
for(int y = 0; y < bmp_h; ++y) {
for(int x = 0; x < bmp_w; ++x) {
COLORREF col = x & 1 && y & 1 ? RGB(255, 255, 255) : RGB(0, 0, 0);
SetPixel(hdcmem, x, y, col);
}
}
// blit image to client area by creating a DIB section and
// copying DIBits to it from hbitmap(works as expected: red&white image)
{
// get DIBits
std::vector<BYTE> vDIBits_buf(pbmi->bmiHeader.biSizeImage);
void* pvBits = vDIBits_buf.data();
SelectObject(hdcmem, hOldBmp); // hbitmap must NOT be selected into a DC before GetDIBits() call as per documentation
if(!GetDIBits(hdc, hbitmap,
0, (UINT)bmp_h,
pvBits, pbmi, DIB_RGB_COLORS)) { // resets biClrUsed & biClrImportant to 0, and pbmi->bmiColors to black&white -- why??
MessageBox(hWnd, L"GetDIBits has failed", L"Failed", MB_OK);
}
// reset members modified(for some reason) by GetDIBits()
// back to their original values
pbmi->bmiHeader.biClrUsed = 2;
pbmi->bmiColors[0] = RGBQUAD{0,0,255,0};
pbmi->bmiColors[1] = RGBQUAD{255,255,255,0};
// copy DIBits from hbitmap to hDIBSecion
void* pvBits_dest = nullptr;
HBITMAP hDIBSecion = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, &pvBits_dest, NULL, 0);
memcpy(pvBits_dest, pvBits, pbmi->bmiHeader.biSizeImage);
// blit hDIBSecion to client area
HGDIOBJ hOldBmp = SelectObject(hdcmem, hDIBSecion);
BitBlt(hdc, 0, 0, bmp_w, bmp_h, hdcmem, 0, 0, SRCCOPY); // blits a red&white image as expected
// clean up
SelectObject(hdcmem, hOldBmp);
DeleteObject(hDIBSecion);
}
// blit image to client area by modifying color table of hbitmap
// (does not work as expected: black&white image instead of green&black)
{
// initialize palette(green&black)
std::vector<BYTE> log_palette_buf(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 2);
LOGPALETTE* plplt = reinterpret_cast<LOGPALETTE*>(log_palette_buf.data());
plplt->palNumEntries = 2;
plplt->palVersion = 0x0300;
PALETTEENTRY pe_black{0,0,0,0};
PALETTEENTRY pe_green{0,255,0,0};
plplt->palPalEntry[0] = pe_green;
plplt->palPalEntry[1] = pe_black;
// modify color table of hbitmap to green&black
HGDIOBJ hOldBmp = SelectObject(hdcmem, hbitmap); // select hbitmap into memory DC first
HPALETTE hp = CreatePalette(plplt);
HPALETTE hp_old = SelectPalette(hdcmem, hp, FALSE);
RealizePalette(hdcmem); // supposed to modify color table of selected bitmap(hbitmap) according to documentation
// blit hbitmap to client area
BitBlt(hdc, bmp_w, 0, bmp_w, bmp_h, hdcmem, 0, 0, SRCCOPY); // ???blits a black&white image???
// clean-up
SelectObject(hdcmem, hOldBmp);
SelectPalette(hdcmem, hp_old, FALSE);
DeleteObject(hp);
}
// clean up
DeleteObject(hbitmap);
DeleteDC(hdcmem);
ReleaseDC(hWnd, hdc);
}
我错过了什么?