Windowsでは、描画はWM_PAINTのハンドラ内で描画するのが基本です。
これは、貴方が意識しないタイミングでOSがWM_PAINTを発行する可能性があることを
示しています。例えば、他のウインドウが上に重なってそのウインドウが移動、または
消えた場合などです。
その他、サイズが変わった、最小化状態から元に戻った、最大化から元に戻ったなどなど。
来るタイミングが想定できない以上、そのウインドウの描画はWM_PAINTの中に全て収められて
いるか、その中から呼び出されている必要があります。
しかも、その時のウインドウの状態を考慮してその時の状態にあった描画を行う必要があるので
す。
この話は、Windowsでプログラミングする場合、基本になる部分になります。
Windows上のプログラムがどういった仕組みで動作しているのかをきちんと学習されることを
お勧めします。
WM_PAINT内でそのウインドウに何を描画するべきなのかをフラグ等で管理しておき、
状態の変化に応じてそれらのフラグ等を操作する必要があると考えた方がいいと思います。
また、描画は、独自のメッセージを投げるのではなくて、状況を示すフラグ等の操作を行い、
Invalidateなどの画面の無効化を呼ぶようにした方が、仕組み的にはいいと思います。
>・FileDialog 呼び出し で無効化領域ができる
>・メッセージ IDM_UE を処理し、無効化領域に一旦グラフが描かれる
ここで処理が終わり、メッセージキューが空になったので、
この時点でOSからWM_PAINTが投げ込まれます。
デフォルトのWM_PAINT処理ではBeginPaintを呼び、それによってWM_ERASEBKGND
が発行されます。
デフォルトのWM_ERASEBKGND処理では無効領域だけをデフォルトブラシで
塗りつぶします。
WM_PAINTを独自にハンドリングした場合、BeginPaintを呼ばなければ、
WM_ERASEBKGND処理は行われないでしょう。BeginPaintを呼んでもデフォル
トのWM_ERASEBKGND処理が行われる限り結果は同じです。
もし、ファイルダイアログに隠れていた領域以外の全画面が消去されると
いうのであれば、それは私が以前に言ったInvalidateRect()での全画面無
効化の処理がどこかに残っていたからではないでしょうか?
<!--この話は、Windowsでプログラミングする場合、基本になる部分になります。
Windows上のプログラムがどういった仕組みで動作しているのかをきちんと学習されることを
お勧めします。
-->
PATIOさんのおっしゃられる通りです
<1--
もし、ファイルダイアログに隠れていた領域以外の全画面が消去されると
いうのであれば、それは私が以前に言ったInvalidateRect()での全画面無
効化の処理がどこかに残っていたからではないでしょうか?
-->
Wanderer さんのご指摘について
WM_PAINT:
hdc=beginPaint(hwnd,&ps)
で hwnd に Dialog に隠されるエリアの HWND を指定していました
Client Area の HWND に変更すること隠された部分だけがバックグラウンドになりました
いろいろ調べててみました
●無効領域が有効になるとき
1.次のWM_PAINTメッセージが発生して処理される
2.ValidateRect()
3.UpdateWindow() WM_PAINT メッセージが送られるため有効になる
●解決
・グラフが描かれなかった理由
(1)WM_PAINT 呼び出しの機会が無かった
・無効領域が生じたとき WM_PAINを使用せずに描く方法
無効領域が生じた
ValidateRect() で有効化(または、UpdateWindow() )
hDC=GetDC(hwnd)
hDC に描画
●でも、これはあくまでも邪道であり、ご指摘のように
多くのボタンで、度々、時間のかかる画面を書き換えるプログラムでも
メモリデバイスに描いた図形を,WM_PAINT内でBitBltするのが
正しい方法ですね
ありがとうございました
●残った疑問
(1)case IDC_READ:
FileDialogBox 呼び出し
//ValidateRect() で有効化
メモリデバイス作成
メモリデバイスに描画
BitBlt()
----->ValidateRect()が無いと描画しません
あれば描画します
(2)case IDC_READ:
FileDialogBox 呼び出し
ValidateRect() で有効化
メモリデバイス作成
メモリデバイスに描画
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
BitBlt(hdc, メモリデバイス, );
EndPaint(hwnd,&ps);
では描画されません
(3)cue にポストする、しないの違い
(1)はこれまでの処理と同じとです。
1.FileDialogBoxで無効化領域が出来ます。
2.BitBlt()で描画しますが、直後に WM_PAINTが発行され、WM_ERASEBKGND
が働いて消されます。
ValidateRect()ですべて有効にしてやると、OSはWM_PAINTを発行しないの
で、WM_ERASEBKGNDが働かず、描画されたものが残ります。(前回の私の説
明はちょっと言葉足らずでしたね)
(2)
1.FileDialogBoxで無効化領域が出来ます。
2.ValidateRect() で無効領域がなくなります。
3.どこも無効化されていないので、OSはWM_PAINTを発行しません。したが
って描画されません。
2の処理をなくすと正常にWM_PAINTが働きます。
ただし、FileDialogBoxを画面とは全然別のところに表示したりすると、無
効領域ができないので、WM_PAINTが発行されない可能性があります。case IDC_READ
では、PATIOさんのおっしゃるように最後に InvalidateRect()を呼んで画
面を無効化し、WM_PAINTの発行をOSに促すべきかと思います。
(3)はちょっとおっしゃっている意味がわかりかねるのでもう少し詳しく
お聞かせください。