Win32 / GDI:如何使用RealizePalette()修改颜色表?

时间:2017-10-06 17:19:05

标签: c++ winapi gdi

根据关于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);
}

我错过了什么?

0 个答案:

没有答案