エアロ有効時、モノクロBMPへの転送に失敗するのは?

解決


Boku  2013-02-09 12:29:48  No: 73613  IP: 192.*.*.*

環境:VC2003 & MFC

お世話になります。
SDIプログラムで、クライアント領域の内容をモノクロBMP画像としてクリップボードにコピーする処理を、下のように記述しています。
(コピーされる領域の内容は、カラーではなく白黒です。)

HDC hScrnDC, hMemDC;
HBITMAP hBmp;
CRect rect;
const int width = 100;  // 転写サイズ(幅)
const int height = 50;  // 転写サイズ(高さ)

// クライアント領域の、デスクトップ上での座標を取得
GetClientRect(&rect);
ClientToScreen(&rect);

// 画面内容を転送
hScrnDC = CreateDC("DISPLAY", NULL, NULL, NULL);
hMemDC = CreateCompatibleDC(hScrnDC);
hBmp = CreateBitmap(width, height, 1, 1, NULL); // モノクロのビットマップを作成
SelectObject(hMemDC, hBmp);
ASSERT(GetBkColor(hScrnDC) == RGB(255,255,255));
BitBlt(hMemDC, 0, 0, width, height, hScrnDC, rect.left, rect.top, SRCCOPY);

// クリップボード処理
OpenClipboard(m_hWnd);
EmptyClipboard();   
SetClipboardData(CF_BITMAP,hBmp);
CloseClipboard();

// 後始末
DeleteDC(hMemDC);
DeleteDC(hScrnDC);

Windows XPまではこれで動いていたのですが、Windows Vista/7でエアロが有効になっていると、コピーされた画像が真っ黒になってしまいます。
エアロを一時的に無効にすると(exeのプロパティ→互換性→「デスクトップコンポジションを無効に」をON)、うまく動作します。

CreateBitmap()のかわりにCreateCompatibleBitmap()を使用すると、エアロがオンでも正しくコピーされるのですが、出来上がるBMPがモノクロ(1bitカラー)の形式ではなくなってしまいます。

Webで調べていると、とあるページに、以下のようなことが書いてありました。
> BitBltではカラービットマップをモノクロビットマップへ転送する場合、「元画像の背景色は白(1)、それ以外の色は黒(0)として扱われる」ようです

そこで、
 転送元DCの、"指定されている背景色(GetBkColor()で得られる値)"と、"見た目上の背景色(白)" が一致していないのでは?
 そのために、転送後の全画素が黒になるのでは?
と考え、GetBkColor()で転送元の背景色を調べてみましたが、エアロON時/OFF時ともに白になっているようでした(ソース中のASSERTマクロの部分です)

以上、どこに問題があるのでしょうか?
よろしくお願いいたします。

編集 削除
Boku  2013-02-12 22:25:40  No: 73614  IP: 192.*.*.*

自己レスです。

質問させていただいた件、原因がわからないため、別のやり方で実装してしまいました。

具体的には、
・CreateBitmap()によるモノクロBMPの作成はあきらめて、CreateCompatibleBitmap()でカラーのBMPを作成する
・そのカラーのBMPを元に、GetDIBits()でモノクロのBMPファイル(一時ファイル)を作成する
・LoadImage()でそのモノクロBMPファイルのハンドルを取得し、それをもとにクリップボードにコピーする
以上です。

いちいち一時ファイルを作成しなくてもできるのかもしれませんが、よくわからなかったので・・・。

以上、釈然としませんが、とりあえずやりたいことはできましたので、解決ということにさせていただきます。
ありがとうございました。

編集 削除