アプリ版:「スタンプのみでお礼する」機能のリリースについて

お世話になります。
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;

A 回答 (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の解放を忘れないでちょーだい!
解放する順番によってメモリリークがおきちゃうぞ
後に作成したものを先に解放するのだー

おちまい
    • good
    • 0
この回答へのお礼

動きました!表示できました!
SelectObject意味や役割の理解が一歩進みました。
目からウロコだのなんだの色々落ちまくりです。

回答ありがとうございました。

お礼日時:2004/08/06 08:12

>とりあず付け焼刃の知識で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);
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
すいません、お礼がすっかり遅くなってしまいました。(^^;

すばらしい!
必要な関数や変数が一目瞭然で、非常に参考になります。
残念ながら勉強不足で、まだ応用できるレベルに達していないのですが、勉強を終えて応用が利くようになったらぜひ試してみます。

回答本当にありがとうございました。

お礼日時:2004/08/05 01:49

省略されている部分にあるのかもしれませんが、


メモリDCの書き込み対象は、そのメモリDCにSelectObjectされたビットマップになります。
CreateDIBSectionなどで作成することが多いです。

SelectObjectで戻ってきたビットマップを再度SelectObjectしないと、DeleteDCは失敗します。
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。
SelectObjectですか。今は使っていないです。
これが原因でしょうか。

とりあず付け焼刃の知識でSelectObjectを使ってみたのですが、やはり表示されません。というか、修正量が多くてもはやどこまで正常なのかさえ分からなくなってしまってるんですけど。
もっと簡単なものかと思っていたのですが、やはり何事も基本を抑えないとだめですね。。。

今回はいったん質問を締め切り、改めて勉強しなおして出直します。
そのときはまたよろしくお願いします。

お礼日時:2004/07/19 17:08

ふつうは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 …
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。

>ふつうはWM_PAINTなんかでそんなことしないんですけどね。描画にコストがかかるからこそメモリデバイスコンテキストを使うんですから。

勉強不足による設計思想のまずさから、今となっては現在の設計を変更するのが困難な造りになってしまっています。(実は今日も挑戦してみたのですが、連鎖的に問題が増える一方です。根本的解決には設計からやり直した方がよさそうなので、今のところは見送ろうと思います。)

>WM_PAINTの中ではBitBltのみ。
>CreateCompatibleDCで元にするHDCはBeginPaintではなくGetDCとかですかね。

おお!!
前者は(前述の理由で)後に回すとして、とりあえず
hMemDC = CreateCompatibleDC(GetDC(hWnd));
としてみました・・・・が、まだ同じ状況です。
うーん、作り直したほうが早いかなぁ。。。

アドバイスおよび細部にまでわたるチェックありがとうございます。
これから参考サイトでじっくり腰を据えて勉強します。

お礼日時:2004/07/19 00:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!