タイトルそのまんまで質問です。
今、自分はビットマップをメモリデバイスコンテキスト(HDC)を使っていたのを
DIBに変えてみました。
HDCを使っていたときは、もう一つメモリを作っておき、マスクを描画しといて、
それを表に描画するときに透過処理をしていました。
けれど、DIBのほうはそんな方法使えないので、どうしたらいいのか困っています。
なにか良い方法は無いでしょうか?よろしくお願いします。
ついでに、HDCを使っていたときは以下のようにしていたのですが、
HDC hDC01, hDC01_mask;
HBITMAP hBmp01, hBmp01_mask;
WinAPI.....
{
WM_CREATE:
hBmp01 = LoadImage();
hdc = GetDC(hWnd);
hDC01 = CreateCOmpatibleDC(hdc);
SelectObject(hDC01, hBmp01);
DeleteDC() // Release?
CreateMask(hDC01, hDC01_mask, hBmp01, &hBmp01_mask);//マスクを作る関数
//hDC01_mask と hBmp01_mask にマスクが作られる
WM_PAINT:
BitBlt(hdc, ..... , hDC01_mask, SRCAND);
BitBlt(hdc, ......, hDC01, SRCPAINT);
WM_CLOSE:
DeleteDC(hDC01);
DeleteObject(hBmp01);
DeleteDC(hDC01_mask);
Deleteobject(hBmp01_mask);
}
色々なプログラムを見ていると、メモリデバイスを取得したらすぐ破棄しているのですが、
このように長期(プログラムの最初から最後まで)にわたって使っても大丈夫なのでしょうか?
環境いい忘れました。
VC++.NET の WindowsXP です。
メモリDC を DIB にした、とはどういうことでしょうか?
そこがいまいち掴めていません。
> 色々なプログラムを見ていると、メモリデバイスを取得したらすぐ破棄しているのですが、
> このように長期(プログラムの最初から最後まで)にわたって使っても大丈夫なのでしょうか?
そのプログラムを見る限りでは、WM_CREATE で CreateCompatibleDC し、WM_CLOSE で DeleteDC しているようですので、この Create / Delete の対応が一対一であれば問題はありません。
システム内に存在できる DC の数は決まっていて、そんなに多くないので、アプリは可能な限り早く削除しないと、他のアプリが DC を取得できなくなる、という解説も見たことがありますが、デマ、あるいは昔の仕様かと思われます。
GetDC の説明には
> デバイスコンテキストの数は、利用可能なメモリの量によってのみ制限されます。
と書かれていますので。
> hdc = GetDC(hWnd);
> hDC01 = CreateCOmpatibleDC(hdc);
> SelectObject(hDC01, hBmp01);
> DeleteDC() // Release?
この DeleteDC は何を消去しているのでしょうか?
GetDC で取得したものならば、ReleaseDC で解放すべきです。
Get / Release、Create / Delete が対になります。
> メモリDC を DIB にした、とはどういうことでしょうか?
> そこがいまいち掴めていません。
今まではビットマップをメモリ DC に選択したものを保持していたところ、これからは DIB のビットマップハンドルを持っておくようにした、ということでしょうか?
DIB の直接描画といえば、SetDIBits、SetDIBitsToDevice、StretchDIBits などがあります。このうち、StretchDIBits だけがラスタオペレーションコードを渡せるようですが…
説明不足ですみません・・・。
DCをDIBにしたというのは、今まではメモリDCにHBITMAPを描画して、
それを表に描画としていました。でも今作っているプログラムでは
WM_PAINT 時に何回もそれで描画してるので、別の質問のときに処理が重いと指摘されました。
なので、そこでもらったアドバイスにDIBを使うと良い、といわれたので、
HBITMAP→DC→クライアント ではなく、
グローバルな変数 HBITMAPINFO * bmpInfo ,BYTE * bPix のように宣言して、
それをStretchDIBitsでクライアントに描画しています。
その際、描画に透過処理をしたいのですが、方法が分りません。
なにか、方法は無いでしょうが?
>なので、そこでもらったアドバイスにDIBを使うと良い、といわれたので、
そんな事はありません。StretchDIBtisを使う度にDIB-DDB変換が行われるので、
かえって重くなります。
WM_PAINTのたびにメモリDCをCreateCompatibleDCすると重いので、
グローバルにして使いまわすだけで正解だと思います。
どうしてもDIBで行いたい場合は、CreateMaskのDIB版を作成する必要があります。
ソースがちょっとおかしいです。
WM_CREATE:
hBmp01 = LoadImage();
hdc = GetDC(hWnd);
hDC01 = CreateCOmpatibleDC(hdc);
// SelectObject(hDC01, hBmp01);
// hDC01がもともと持っているHBITMAPが行方不明になっています。
HBITMAP preBmp = SelectObject(hDC01, hBmp01);
// preBmpは2度と使わないのならDeleteする。
DeleteObject(preBmp) ;
//DeleteDC() // Release?
ReleaseDC(hdc) ;//シャノンさんの指摘の通り
CreateMask(hDC01, hDC01_mask, hBmp01, &hBmp01_mask);//マスクを作る関数
//hDC01_mask と hBmp01_mask にマスクが作られる
WM_PAINT:
BitBlt(hdc, ..... , hDC01_mask, SRCAND);
BitBlt(hdc, ......, hDC01, SRCPAINT);
WM_CLOSE:
DeleteDC(hDC01);
//DeleteObject(hBmp01);
// hDC01がDeleteされる時に選択されているHBITMAPは同時に破棄されるので
// hBmp01の破棄は不要。
DeleteDC(hDC01_mask);
Deleteobject(hBmp01_mask);
てつやさん、アドバイスありがとうございます。
てつやさんの言うとおり、グローバルのメモリDCにしようと思います。
ツイート | ![]() |