クリップボードからプログラムに画像を貼り付けています。ビットマップはバックグラウンド memDC ビットマップに配置され、画面に描画される前に別の memDC と合成されます。バックグラウンド ビットマップは、1 ピクセルあたり 8 ビットです。問題は、bitblt が Black (0x00000000) を Most-Black (0x00010101) に変えることです。同じものを MSPaint に貼り付けると、Black になります。MSPaint から Black をコピーすると、Almost Black が得られます。(他の色もバラバラです)。背景のビットマップを 32bpp に変更すると、正しい色が得られますが、現時点ではオプションではありません。
以下は、この問題を示すコードです。
/*
*HWND hWnd; // main window handle
*HDC hDC; // main window DC (set elsewhere)
*HDC memDC; // background DC (set elsewhere)
*/
HBITMAP hClipBitmap=NULL;
OpenClipboard(hWnd);
hClipBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
if (hClipBitmap!=NULL)
{
// I now want to make a copy of the bitmap
BITMAP bm;
HDC hSrcDC,hDestDC;
HANDLE OldObject1, OldObject2;
DWORD sz = GetObject(hClipBitmap, sizeof(BITMAP), &bm);
if(sz == sizeof(BITMAP))
{
// make a bitmap to allow positioning before actual pasting
hPasteBitmap = ::CreateCompatibleBitmap(memDC, bm.bmWidth, bm.bmHeight);
if (hPasteBitmap==NULL)
FATAL_ERROR;
hSrcDC = CreateCompatibleDC(hDC);
hDestDC = CreateCompatibleDC(hDC);
OldObject1 = SelectObject(hSrcDC, hClipBitmap); // bpp is 32
OldObject2 = SelectObject(hDestDC, hPasteBitmap); // bpp is 8
BitBlt(hDestDC, 0, 0, bm.bmWidth, bm.bmHeight, hSrcDC, 0, 0, SRCCOPY);
COLORREF color2 = ::GetPixel(hSrcDC, 1, 1); // color2 is 0x00000000
COLORREF color3 = ::GetPixel(hDestDC, 1, 1);// color2 is 0x00010101
COLORREF color4 = ::GetNearestColor(hSrcDC, color2); // 0x00000000
COLORREF color5 = ::GetNearestColor(hDestDC, color2);// 0x00000000
// hPasteBitmap now contains the clipboard data
}
}
// other cleanup snipped for clarity
GetPixel() と GetNearestColor() を使用すると、探している結果が得られるはずですが、そうではありません。ある種のパレット操作が欠けていると思いますか?
アップデート
私が本当に問題を抱えている部分は、これらの API のポイントを誤解している可能性がありますが、ピクセルの色を照会し、そのために使用する色をコンテキストに尋ねると、正しい色 (黒) が返されることです。 BitBltが生成するAlmost Blackの代わりに。
他のプログラムはクリップボードにパレットを置かないようです - おそらくパレットを必要としない 32bpp ビットマップを置いているからでしょうか? 彼らは、 MSDN のクリップボード変換テーブルに基づいて利用可能なものを見てわかる限り、DIB を行っていません。