お世話になります。
Borland C++ 5.5.1 for Win32で簡易な画像ビュアーを開発しています。
基本的な動作は完成したのですが、ある条件下で発生する問題を回避するために、メモリデバイスコンテキストを用いようと考えています。
ところが、後述のように変更したところ、画像がまったく表示されなくなりました。(ウィンドウ背景色で塗りつぶされたままです。一瞬たりとも表示されません。)
Windowsプログラムに慣れていないため解決に難儀しています。
どなたか原因と対策をご教示くださいますようよろしくお願いします。
//////////////////////////
//変更前 画像表示される//
//////////////////////////
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
/* ~省略(画像処理)~ */
StretchDIBits(hdc,~,SRCCOPY);//処理した画像をウィンドウへ
EndPaint(hWnd, &ps);
break;
////////////////////////////
//変更後 画像表示されない//
////////////////////////////
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
hmemdc = CreateCompatibleDC(hdc);
/* ~省略(画像処理)~ */
StretchDIBits(hdc,~,SRCCOPY);//処理した画像をMemoryDCへ
BitBlt(hdc, 0, 0, rc.right, rc.bottom, hmemdc, 0, 0, SRCCOPY);//MemoryDCからウィンドウへ(rcはクライアント領域)
DeleteDC(hmemdc);
EndPaint(hWnd, &ps);
break;
No.4ベストアンサー
- 回答日時:
StretchDIBitsは、hdcへ出力しているぞ
hmemdcへは何も出力していないみたいだぞ
その後、BitBltでhmemdcをhdcへ出力しているから
何にも表示されないのだ
メモリデバイスコンテキストでやりたいなら、
1.CreateCompatibleBitmapで空のHBITMAPを作成する
2.SelectObject(hmemdc, hBitmap)とかで、hmemdcに
空のHBITMAPをくっつける
(これで、hmemdcへの描画処理がhBitmapのメモリに
描かれることになる)
3.StretchDIBitsでhmemdcに出力する
(画像データ -> hBitmap)
4.BitBltでhmemdcをhdcへ出力する
(hBitmap -> ディスプレイ)
※hBitmapとhmemdcの解放を忘れないでちょーだい!
解放する順番によってメモリリークがおきちゃうぞ
後に作成したものを先に解放するのだー
おちまい
動きました!表示できました!
SelectObject意味や役割の理解が一歩進みました。
目からウロコだのなんだの色々落ちまくりです。
回答ありがとうございました。
No.3
- 回答日時:
>とりあず付け焼刃の知識でSelectObjectを使ってみたのですが、やはり表示されません。
言葉で説明するのは難しいですね。
おそらく、StretchDIBitsでの画像の拡縮に時間がかかるから、画像の読み込み時に拡縮をやって、あとはBitBltでできるだけ高速に描画させるという方針だと思います。
だとすると、CreateCompatibleBitmapでビットマップを作成するのがいいです。CompatibleBitmapはVRAMに空きがあればそこに置かれるようなので、BitBltが桁違いに速いです。
1.画像の読み込み
HBITMAP imageBm = 画像の読み込み();
HDC dispDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(dispDC);
HBITMAP memBm = CreateCompatibleBitmap(dispDC, IMAGE_WIDTH, IMAGE_HEIGHT);
HGDIOBJ prevMemBm = SelectObject(memDC, (HGDIOBJ)memBm);
StretchDIBits(memDC, ...);// memDCを通してmemBmにimageBmを書き込む
DeleteDC(dispDC);
DeleteObject((HGDIOBJ)imageBm);
2.WM_PAINT
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
BitBlt(hdc, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, memDC, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
3.画像の開放
SelectObject(memDC, prevMemBm);
DeleteDC(memDC);
DeleteObject((HGDIOBJ)memBm);
回答ありがとうございます。
すいません、お礼がすっかり遅くなってしまいました。(^^;
すばらしい!
必要な関数や変数が一目瞭然で、非常に参考になります。
残念ながら勉強不足で、まだ応用できるレベルに達していないのですが、勉強を終えて応用が利くようになったらぜひ試してみます。
回答本当にありがとうございました。
No.2
- 回答日時:
省略されている部分にあるのかもしれませんが、
メモリDCの書き込み対象は、そのメモリDCにSelectObjectされたビットマップになります。
CreateDIBSectionなどで作成することが多いです。
SelectObjectで戻ってきたビットマップを再度SelectObjectしないと、DeleteDCは失敗します。
アドバイスありがとうございます。
SelectObjectですか。今は使っていないです。
これが原因でしょうか。
とりあず付け焼刃の知識でSelectObjectを使ってみたのですが、やはり表示されません。というか、修正量が多くてもはやどこまで正常なのかさえ分からなくなってしまってるんですけど。
もっと簡単なものかと思っていたのですが、やはり何事も基本を抑えないとだめですね。。。
今回はいったん質問を締め切り、改めて勉強しなおして出直します。
そのときはまたよろしくお願いします。
No.1
- 回答日時:
ふつうはWM_PAINTなんかでそんなことしないんですけどね。
描画にコストがかかるからこそメモリデバイスコンテキストを使うんですから。WM_PAINTの中ではBitBltのみ。
CreateCompatibleDCで元にするHDCはBeginPaintではなくGetDCとかですかね。
http://www13.plala.or.jp/kymats/explain/gameprog …
参考URL:http://www13.plala.or.jp/kymats/explain/gameprog …
アドバイスありがとうございます。
>ふつうはWM_PAINTなんかでそんなことしないんですけどね。描画にコストがかかるからこそメモリデバイスコンテキストを使うんですから。
勉強不足による設計思想のまずさから、今となっては現在の設計を変更するのが困難な造りになってしまっています。(実は今日も挑戦してみたのですが、連鎖的に問題が増える一方です。根本的解決には設計からやり直した方がよさそうなので、今のところは見送ろうと思います。)
>WM_PAINTの中ではBitBltのみ。
>CreateCompatibleDCで元にするHDCはBeginPaintではなくGetDCとかですかね。
おお!!
前者は(前述の理由で)後に回すとして、とりあえず
hMemDC = CreateCompatibleDC(GetDC(hWnd));
としてみました・・・・が、まだ同じ状況です。
うーん、作り直したほうが早いかなぁ。。。
アドバイスおよび細部にまでわたるチェックありがとうございます。
これから参考サイトでじっくり腰を据えて勉強します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
画像処理 ビットマップ ダブ...
-
マインクラフト(pc版)で座標...
-
エクセルで作った新しいウイン...
-
コントロールの書式設定で、“コ...
-
作成したウインドウのサイズを...
-
Minecraft 統合版(PC)の描画距...
-
コンボボックス内の文字サイズ変更
-
「アイテムは収集されました」...
-
ブレゼンハムのアルゴリズムに...
-
カーソルが自分のウィンドウか...
-
vbaから他のアプリを終了
-
C言語 配列で座標
-
グラフの交点の求め方(Excel)
-
スクロールバーを点滅させない方法
-
panelのスクロール表示について
-
勝手にウィンドウが開いて止ま...
-
描画を透明にする方法
-
他のウィンドウのボタンを自動...
-
MATLABを使った三次元座...
-
VBAで単一ブック複数窓を閉じる...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コンテキスト依存とは?
-
画面がチカチカする
-
VC++のTextOutの再描画の仕方
-
コントロール内の文字の背景色
-
ビットマップ(表示速度とサイズ)
-
VBでFD、USBの有効・無効...
-
Rectangleで、リソースが解放さ...
-
WinAPIでスクリーン画像を映し...
-
メモリデバイスコンテキストを...
-
クライアント領域をCBitmapに取...
-
ダブルバッファの作り方
-
VC++でopenGLを利用したい...。
-
C 多角形を半透明に塗る方法
-
Win32APIにて、アイコンの情報...
-
ExtTextOut
-
TextOutについて
-
ハードコピーをプログラムから...
-
Windowsプログラミング 画面描...
-
BeginPaintの使い方
-
デバイスコンテキストの宣言に...
おすすめ情報