ペイント・イベントでの再描画について

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
メッセージ
作成者
jacoby
記事: 106
登録日時: 2006年6月02日(金) 18:20

ペイント・イベントでの再描画について

#1 投稿記事 by jacoby »

ウインドウをリサイズした時のペイント・イベントでの再描画について
教えて下さい。

ウインドウのクライアントエリアの大きさに合わせて赤色の
四角ボックスを描画する簡単なテストプログラムを下の様に
書きました。(この質問の末尾にソースを)

まずクリエイトイベントで、
リサイズ時の再描画を自動的に行わないように、
ウインドウクラススタイルの変更をしておきます。
'CS_HREDRAWとCS_VREDRAWを取り除いてセット
SetClassLong(hMainWnd,GCL_STYLE,CS_DBLCLKS)
リサイズとペイントの各イベントではそれぞれが実行されたことを示すために
プロンプト画面に"Resize()"、"Paint()"と表示するようにします。


この設定してからウインドウをリサイズしたとき
 結果は、リサイズでウインドウサイズが以前の状態よりも、
  小さくなるとき--->ペイント・イベントは実行されない
  大きくなるとき--->ペイント・イベントは実行される
 となるようです。
ここで気になるのが「ウインドウサイズが大きくなるとき」の動作。
ペイント・イベントへ確かに飛んでいる筈ですが
(プロンプト画面に"Paint()"と表示される)、
クライアントエリア全体は再描画されず、あくまでも
ウインドウ枠を広げた分だけのいわゆる「無効領域」だけが
再描画されている模様。
ただしこのプログラムのペイント・イベントでは「無効領域」は
引数として受け取っておらず、常に画面全体を再描画するような
形になっているので、部分的な無効領域の再描画はそもそも
無理なハズと思うのですが。。

もちろん「リサイズ・イベント」内に
 InvalidateRect(hMainWnd, ByVal NULL, FALSE)
と一文書けば何故か解決するのですが、書かなくとも
大きくなるときにはペイントイベントに飛んでいってるようなので、
重複することなら出来れば避けたいと思います。

それ以前にやはり、このペイントイベントが実行されているなら
クライアントエリアは「必ず」全体が再描画されるのではないかと。。
このことがどうにも腑に落ちないでいます。

ウインドウをリサイズした時のペイント・イベントでの再描画について
お知りの方がおられましたら教えて下さい。

(AB4.24/WinMe)
Toshi
記事: 98
登録日時: 2005年7月19日(火) 19:47
お住まい: 山形県

#2 投稿記事 by Toshi »

CS_HREDRAW / CS_VREDRAW は、サイズ変更時に「クライアント領域全体」を再描画するためのフラグです。
このフラグが指定されていなければ、サイズ変更時はその広がった部分のみが無効領域となり再描画の対象となります。
つまり、サイズ変更時は(無効領域がクライアント領域全体か広がった部分のみかの違いがあるだけで)
フラグの指定の有無に関係なく WM_PAINT メッセージが飛んでくるのです。

そして、無効領域が広がった部分のみの場合、その外へ描画しても反映されません。
なぜなら、(Callback.wbp を見ると分かりますが)Paint イベントの引数である hDC は、
BeginPaint API から返された、あらかじめクリッピング リージョンが設定されているものだからです。
jacoby
記事: 106
登録日時: 2006年6月02日(金) 18:20

レスありがとうございます。

#3 投稿記事 by jacoby »

レスありがとうございます。
そして、無効領域が広がった部分のみの場合、その外へ描画しても反映されません。
なぜなら、(Callback.wbp を見ると分かりますが)Paint イベントの引数である hDC は、
BeginPaint API から返された、あらかじめクリッピング リージョンが設定されているものだからです。

Callback.wbpを覗いてみるとご指摘の通り
確かにこう書かれていました。

コード: 全て選択


Case WM_PAINT
  Dim ps As PAINTSTRUCT
  Dim hDC As HDC
  hDC=BeginPaint(hWnd,ps)
  MainWnd_Paint(hDC)
  EndPaint(hWnd,ps)
この「Begin(End)Paint」というのは自分が
ABのプロジェクトでプログラムを書いていると
「見ないで終わってしまう」のでロクに理解せずに
来てしまったなぁと反省しています。
「クリッピングリージョン」が設定されているとその外は
いくらペイントイベント内で描画してても実際には反映
されないんですね。
ペイントイベント内の処理は文字通り画面に反映されるもの
と思い込んでいましたから。

CS_HREDRAW / CS_VREDRAWについては
リサイズ時の再描画の「ちらつきを抑制するため」に
というのでどこかで調べたのをそのまま使っていました。
ということはこれ自体は「再描画のちらつき」には本質的には
関係してないのでしょうか?
確かにこれを外すとリサイズ再描画時に一度背景色(?)で
塗りつぶさなくなるようなので重宝して書いてました。
検索して調べてみると次のような記事を見つけました。
http://social.msdn.microsoft.com/forums ... 97d838262/
これによるとCS_HREDRAW / CS_VREDRAWは外さなくていいような
ことが書かれていますが、、
まだ自分で確かめていないので何とも、なのですが、、
取り急ぎ、書いて頂いたレスのお礼までに。
ありがとうございました。
またよろしくお願いします。