HDC hdc;
HBITMAP hBitmap;
HDC hMemDC;
CDC* pDc;
pDc = mPictureCtrl.GetDC(); //DC取得
hdc = pDC->GetSafeHdc(); //ハンドル取得
hMemDC = CreateCompatibleDC(hdc); //メモリDCを作成
hBitmap = CreateCompatibleBitmap(hdc, 800, 600);//DCに関連付けられた互換性のあ
るBMPを作成
SelectObject(hMemDC, hBitmap); //ビットマップを選択
//描画
SelectObject(hMemDC,GetStockObject(GRAY_BRUSH));
Rectangle(hMemDC,25,25,50,50);
DeleteObject(hBitmap); //不用になったBMPを削除
BitBlt(hdc, 0, 0, 800, 600, hMemDC, 0, 0, SRCCOPY);//ビットマップ描画
PictureControlにビットマップを描画したく、上記のようなプログラムを
作りました。DC関連の知識が浅く、ここまで作成したのはよいのですが
以下をどのように実現するのかわかりません。ご教授お願い致します。
1.hdc=GetDC(hWnd);
このようにハンドルを取得した場合、ReleaseDC(hWnd,hdc);
と、解放することとありますが、上記のようにpDC->GetSafeHdc();と
した場合、解放は不要なのでしょうか?
2.描画している部分ですが、本来はhMemDCに対してビットマップを描画したいので
す。
ただ、ビットマップは、BITMAPINFOHEADERと、イメージデータ部(BYTE配列)にな
っています。
これを高速に描画させる場合の手段がわかりません。
すみません、環境を書き忘れました。
環境はXP、VC2005、MFCです。
1. 「GetSafeHdc()」は、単にHWNDがNULLでない時にCDCを取得するだけです。
「GetSafeHdc()」を使っても開放はしなければなりません。
補足、
「GetSafeHdc()」を使えばすべて安全というわけではないので、
心配のところは、「HWND ==NULL」のところで処理しないようにしたほうがいい
と思います。
ITOさん
そうですか、わかりました。
mPictureCtrl.GetDC()->ReleaseOutputDC();
として解放するようにしました。
ありがとうございます。
あとはビットマップ・・・
>1. 「GetSafeHdc()」は、単にHWNDがNULLでない時にCDCを取得するだけです。
すみません、CDCでなくHDCです。
すいません、間違っていたら申し訳ないのですけれど。
CDC::GetSafeHdcは、単純にCDC自身が存在していたらメンバー変数のm_hDCを返却するだけ
の実装だと思うのですけれど、この場合もReleaseDCの必要はあるんでしょうか?
内部的に::GetDCを読んでいるとかならわかるんですけれど、メンバー変数を返すだけの
実装の場合、逆にReleaseDCしてしまうと拙いケースもあるような気がするのですが。
例えば、CDCからGetSafeHdcしたものをReleaseDCしてしまった後、CDCのメンバー関数を
呼ぶと拙いのではないかなぁと言う気がします。
CDCのGetSafeHdcの場合はm_hDCの後始末はCDCのデストラクタに委ねた方が良いのでは
と言う気がします。
ちなみにGetSafeHdcで取得したHDCに関しては、NULLチェックは必要ですね。
NULLが返ってきているときは目的の物は取れていない事になりますから。
>mPictureCtrl.GetDC()->ReleaseOutputDC();
>として解放するようにしました。
これでは解放したことにならんでしょう。
mPictureCtrl.GetDC()としてるのだからmPictureCtrl.ReleaseDC()で開放すべきです。
>2.描画している部分ですが、本来はhMemDCに対してビットマップを描画したいので
>す。
> ただ、ビットマップは、BITMAPINFOHEADERと、イメージデータ部(BYTE配列)にな
>っています。
> これを高速に描画させる場合の手段がわかりません。
hMemDCへの描画はSetDIBitsToDeviceでできるでしょう。
毎回呼ぶと効率が悪いので普通DIBSectionに変換します。
よくわからなければCImageクラスを使ってください。
すみません、PATIOさんのご意見通りだと思います。
CDC::GetSafeHdcの説明に
「出力デバイス コンテキストの m_hDC を取得します。」てありました。
HDCは「pDc = mPictureCtrl.GetDC();」で作成したのを使っていますから、
最後に、mPictureCtrl.ReleaseDC(pDc);
の処理がしてあればいいはずですよね。
ビットマップはDDBなので、そのままでは描画できません。
DrawDib***関数郡を使って変換すると楽かな?
MFCなんだから、HDCまで掘り下げる必要もないような気がするが・・・
>ただ、ビットマップは、BITMAPINFOHEADERと、イメージデータ部(BYTE配列)にな
>っています。
CBitmap、CImageあたりが楽です。
開放といえば、
>SelectObject(hMemDC, hBitmap); //ビットマップを選択
こっちの返り値を残してないのがちょっと気になる。
1に対するアドバイス。
は、不要か。回答でてるね。
2に対するアドバイス。
も不要か。
じゃ蛇足。
DC操作の基本知識ありきの関数ですが、
選択とか解放とか面倒なことは、SaveDC()、
RestorDC()ですべて解消できます。
使い方覚えると便利だけと誤ると・・・。
両刃の刃ですねw
大変遅くなってしましました。
やらなければならないことが沢山あって、そちらの方に時間を費やして
しまいました。ついでに解決できました。
subaruさん
>mPictureCtrl.GetDC()としてるのだからmPictureCtrl.ReleaseDC()で開放すべきです。
なるほど、言われてみればそうですね。mPictureCtrlからDCを取得わけですからね。
ありがとうございました。
+さん
CreateDIBitmapを使うことで解決しました。
を使い、メモリ上のイメージデータ+α(ヘッダ等)でビットマップを作成し、
ここで得たハンドルをメモリデバイスコンテキストに
SelectObjectすることで描画できました。ありがとうございました。
rinさん
SelectObjectの戻り値ですが、最後に元に戻すように変更してあります。
ありがとうございました。