こんにちわ。紅'と申します。
半透明処理についてご教示ください。
環境は VISTA & VC2008( WIN32 / MFC ) です。
以下のコードは、作成済みイメージの特定部位に、半透明処理を利用して薄い色を被せ
る(つもり)で作成しました。
EXCEL などの選択中セルをイメージしていただけるとわかりやすいと思います。
現状では、上記の「薄い色」が表示されず、実行前後で描画されるイメージに変化があ
りません。
コメントアウトしてある BitBlt を有効にすると「薄い色」を表示したい部分が指定し
た色で
塗りつぶされます。また、CImage::AlphaBlend を使用するとイメージ通りに描画されま
す。
色々と試したつもりですが、原因が分かりません。
原因と思われる箇所などをご指摘いただけると嬉しく思います。
{
REC tWorkRect = (描画域取得);
HBITMAP hTranseBitmap = ::CreateCompatibleBitmap( (描画先HDC),
tWorkRect.right, tWorkRect.bottom );
HDC hTranseContext = ::CreateCompatibleDC( (描画先
HDC) );
HBRUSH hBrush = ::CreateSolidBrush( (描画色取
得) );
::SelectObject( hTranseContext, hTranseBitmap );
::FillRect( hTranseContext, &tWorkRect, hBrush );
BLENDFUNCTION tBlendData;
::memset( &tBlendData, 0, sizeof( tBlendData ) );
tBlendData.BlendOp = AC_SRC_OVER;
tBlendData.BlendFlags = 0;
tBlendData.SourceConstantAlpha = (BYTE)( 255.0f * 0.2 );
tBlendData.AlphaFormat = AC_SRC_ALPHA;
::AlphaBlend( (描画先HDC), tWorkRect.left, tWorkRect.top,
tWorkRect.right, tWorkRect.bottom,
hTranseContext, tWorkRect.left,
tWorkRect.top, tWorkRect.right, tWorkRect.bottom, tBlendData );
// ::BitBlt( (描画先HDC), tWorkRect.left, tWorkRect.top,
tWorkRect.right, tWorkRect.bottom,
// hTranseContext, tWorkRect.left, tWorkRect.top,
SRCCOPY );
::SelectObject( hTranseContext, (HBRUSH)NULL );
::DeleteObject( hBrush );
hBrush = NULL;
::SelectObject( hTranseContext, (HBITMAP)NULL );
::DeleteObject( hTranseBitmap );
hTranseBitmap = NULL;
::DeleteDC( hTranseContext );
hTranseContext = NULL;
}
なお、上記のコードは、実際に作成した物から不要部分を除去するなどの手を入れてい
るため
基本的な誤りがあるかもしれませんが、一応、実際の環境ではコンパイルを通し、前述
した程度の動作の
確認を行っています。
以上、よろしくお願いいたします。
改行位置が悪かったようです。見づらくてすみません。
あと、名前欄の入力をミスっていました。「紅'」です。重ねてすみません。
CImage::AlphaBlend のソースを追いかけてみましたが、CImage::Create のフラグに
createAlphaChannel が指定されていない場合、AlphaFormat が 0 になっていますね。
で、あらためて BLENDFUNCTION のドキュメントを見てみると、
> When the AlphaFormat parameter is AC_SRC_ALPHA,
> the source bitmap must be 32 bpp. If it is not,
> the AlphaBlend function will fail.
とか書いてあります。
AlphaBlend function will fail とか書いてあるくせに、戻り値が 1 を返すのがむかつ
きます。
> If the source bitmap has no per-pixel alpha value
> (that is, AC_SRC_ALPHA is not set),
という記述があることからも、AlphaFormat は必ず AC_SRC_ALPHA でなければならないと
いうことはないようですが、0 にすべしとも書いてないのは不親切ですね。
というわけで、AlphaFormat は 0 にするのが正解のようです。
AlphaFormat に AC_SRC_ALPHA を指定するケースというのは
・bitmap が bgra(blue, green, red, alpha)で構成されている時
だけだね。
bitmapにalpha値が存在しない(==32bppのbitmapでない)or alpha値を利用しない場合は
指定しない。
> AlphaBlend function will fail とか書いてあるくせに、戻り値が 1 を返す
こっちの環境で(screenとコンパチブルな)16 bpp のbitmap同士で AC_SRC_ALPHA を指
定して AlphaBlend() を試してみたら一応 0 が返ってきたね。
16bpp以外は試していないので上記以外のケースでどうなるかは判らないけど。
> 0 にすべしとも書いてないのは不親切ですね。
めちゃ同意。
「AlphaFormat has the following value」とあり、following value として
AC_SRC_ALPHA しか載せていない現在のMSDNでは誤解してしまう。
>> AlphaBlend function will fail とか書いてあるくせに、戻り値が 1 を返す
> こっちの環境で(screenとコンパチブルな)16 bpp のbitmap同士で
> AC_SRC_ALPHA を指定して AlphaBlend() を試してみたら一応 0 が返ってきたね。
追試サンクス。
俺が実験したときは、画面のプロパティが 32bit になっていたので、変な形で成功して
いたのかもしれない。
シャノンさん、gak さん、返信をありがとうございます。
試したところ出来ました。感謝します。
MSDN に嘘?が書いてあるって...
この辺りのパラメータは一応いじってみてはいたのですが、
組み合わせが悪かったようです。CImage の作りなど、なにか深そう?ですし、
会社ではやれませんがw週末など暇を見つけて追ってみようと思います。
MFC の中を追ってみるという考えが最近なぜか抜けていました。
こちらも反省点でした。
ありがとうございました。