トップ回答者
Win32 API 描画処理について

質問
回答
-
具体的に、(1)マウスの動きに追従する描画はどのように実施し、(2)マウスの位置以外の場所のクライアント領域の描画はどのように実施しているのでしょうか。
「マウスの位置だけに対して描画する」ということは、それ以外のところは「クライアント領域の描画をやり直す」ということが必要です。
それが単に InvalidateRect で済むのか、もう一工夫が必要なのかは、先に書いたようにあなたがどのような方法を使っているかによりま
す。WM_MOUSEMOVE あたりで差分しか描いていないのであれば、InvalidateRect を呼ぶと「マウスの位置だけに描画する」とした内容が見えなくなるかもしれませんね。(その場合、差分描画をやめてすべて WM_PAINT で描く、差分描画時に一度クライアント領域を描き直して差分を描画するなどかなぁ)
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
- 編集済み AzuleanMVP, Moderator 2012年2月20日 13:47
- 回答としてマーク こってり太郎 2012年2月21日 3:01
すべての返信
-
具体的に、(1)マウスの動きに追従する描画はどのように実施し、(2)マウスの位置以外の場所のクライアント領域の描画はどのように実施しているのでしょうか。
「マウスの位置だけに対して描画する」ということは、それ以外のところは「クライアント領域の描画をやり直す」ということが必要です。
それが単に InvalidateRect で済むのか、もう一工夫が必要なのかは、先に書いたようにあなたがどのような方法を使っているかによりま
す。WM_MOUSEMOVE あたりで差分しか描いていないのであれば、InvalidateRect を呼ぶと「マウスの位置だけに描画する」とした内容が見えなくなるかもしれませんね。(その場合、差分描画をやめてすべて WM_PAINT で描く、差分描画時に一度クライアント領域を描き直して差分を描画するなどかなぁ)
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
- 編集済み AzuleanMVP, Moderator 2012年2月20日 13:47
- 回答としてマーク こってり太郎 2012年2月21日 3:01
-
実装によりますね。
(A)全ての描画をWM_PAINTで行っており、他の場所では行っていない。
つまり、CPaintDC( = BeginPaint())のみ使用しているケース。
この場合の実装ではWM_MOUSEMOVEでは、InvalidateRect()のみを行っている。
(B)WM_MOUSEMOVEタイミングなどでCClientDC(キャッシュDC=GetDC())
を用いて画像を描画しているケース。まず、当然ですが、両者の場合共、画像の矩形を保持していなければ話になりません。
(A.1) WM_MOUSEMOVEがきたら
(A.2) 画像描画フラグをOFF。
(A.3) 現在の画像の矩形RcPitureに対して
InvalidateRect( &RcPiture, TRUE);//背景消去する
(A.4) UpdateWindow(); // 即時にWM_PAINTを発行。画像描画フラグがOFFなので
背景の塗りつぶしのみで、画像は表示されないものとする。
(A.5) 新しい位置にRcPitureを移動。
(A.6) 画像描画フラグをON。
(A.7) 新しい位置の画像の矩形RcPitureに対して
InvalidateRect( &RcPiture, FALSE);//背景消去不要
(A.8) UpdateWindow(); // 即時にWM_PAINTを発行。画像描画フラグがONなので
画像が表示される。
てな感じ。うまくコードすると(A.4)が不要になります。ケース(B)の場合は
(B.1) WM_MOUSEMOVEがきたら、
(B.2) HDC hdcCash = GetDC()する。または、CClientDC hdcCash(this);
(B.3) hdcCashに対して、RcPitureを背景色で塗りつぶす。
(B.4) 新しい位置にRcPitureを移動。
(B.5) その位置に画像を描画(BitBlt等)。
(B.6) ReleaseDC()する。
(B.7) ValidateRect( hwnd, NULL);でクライアント領域全体を「有効」にする。
これにより、WM_PAINTが発生するのを抑制する。ケース(B)の方が簡単ですが、移動しないつまり静的状態と、
移動時で描画方法が変わる点がやや制御が難しい。モードありということです。
ケース(A)は描画の仕組みが簡単ですが、無効にする
矩形の制御と、画像描画フラグの制御にやや手間がかかります。
参考になれば幸いです。
-
描画に関する記述はすべてWM_PAINTにしております.
まずフラグを定義し,
WM_LBUTTONDOWN時にフラグをonにして,
WM_LBUTTONUP時にフラグをoffにし,マウスクリック時にだけ描画が行われるようにしています.
WM_MOUSEMOVE時にフラグがonならば,InvalidateRect関数を呼び出して描画を行っています.
WM_PAINTでは,マウスの位置に対して,BitBlt関数を用いて画像の描画を行っています.
ウィンドウ最小化時や,ウィンドウサイズ変更時に移動時に描画された画像が消え,
最後に描画された画像だけ残るため,単純にクライアント領域の更新ができていないのだと思っていました.
-
それは、自分の発言の(A)のアルゴリズムとは異なりますね。
(A)の手順をみればわかるとおり、この描画フラグはWM_MOUSEMOVE専用で
なければなりません。他の物と共用してはなりません。また、WM_MOUSEMOVE時の再描画のデバッグは他の場合と比べて困難です。
WM_MOUSEMOVE時の描画に関する挙動と関係ない、描画に影響を与える
コードはコメントアウトしておくことをお勧めします。また、HDCの描画は自動的にキャッシュされます。
ブレーク時に、当該描画コードの結果をリアルタイムに確認するには、
その直後に GdiFlush()を行うと良いでしょう。- 編集済み 仲澤@失業者 2012年2月21日 2:31