• ベストアンサー

Windowのちらつき防止

WEB検索をしますと結構情報がヒットしますが、 解決に至ってませんので、よろしくお願いします。 Win32アプリケーションです。 WM_PAINTのタイミングでWindowに文字を描画してますが、 背景の塗りつぶしが原因でちらつきます。 WM_ERASEBKGNDメッセージをつぶせない仕様ですので、 よく用いられる方法で、ビットマップによるダブルバッファリングを行ったところ、 ちらつきが抑えられましたが、極端に遅くなってしまいました。 質問1 ビットマップに描画して画面に転送するという動作は どうしたら早くできるでしょうか? 質問2 どんな方法でも結構ですので、画面のちらつきを抑える方法はないでしょうか? どんなささいなことでもかまいませんので お願いします。 不足している情報がありましたら、ご指摘ください。 補足させていただきます。 こちらの掲示版はなにか返答がなければ、もう本人は何もできませんので。

質問者が選んだベストアンサー

  • ベストアンサー
noname#30727
noname#30727
回答No.6

>スクロールなどによって文字が変わりますので、 >一旦すべて消さないと全部重なって出て来てしまいます。 バッファが不要という意味ではありません。 もの凄く極端ではありますが、例を示します。 CreateCompatibleDCでメモリDCを作成、CreateCompatibleBitmap でデスクトップと同じ大きさのビットマップを作成しメモリDCにSelectObjectしておきます。 このビットマップがバッファとなり、全ての描画は一度ここに行う事とします。 WM_ERASEBKGNDでは何もしないで下さい。 WM_PAINTは、BeginPaintを行う前に、 CreateRectRgn(0, 0, 0, 0); と空のリージョンを作り、GetUpdateRgnで更新領域を取得します。その後にBeginPaintします。 取得した更新領域を、メモリDCにSelectObjectして下さい。 WM_ERASEBKGNDで行っていた処理を先に行い、その後に文字等を普通に描画します。リージョンがSelectされているので、更新された領域以外には描画されません。この事は通常の描画と同じです。 メモリDCをクライアントにBitBltすれば描画は全て終わりです。ウィンドウの更新領域以外は転送されませんので、更新領域が小さい時は短時間で終了します。 最後にSelectObjectでメモリDCのリージョンを戻し、DeleteObjectでリージョンを削除して下さい。 より省メモリにする方法は色々と考える事ができますが、描画を見せない基本的な概念はこんな感じになると思います。 ウソがあるかもしれないので、自信なしです。

milkoX
質問者

お礼

すいません、ありがとうございます。 書かれた内容と同じ処理をやっていたのですが、 なぜか極端に遅くなってしまっていたのです。 由一の違いはメモリDCに更新リージョンをセットしなかったことでした。 やってみたところ、かなりよくなりました。 またいろいろと問題が生じるかもしれませんが、 とりあえず様子見とします。 大変お世話になりました。 ありがとうございました。

その他の回答 (5)

  • macchun
  • ベストアンサー率50% (3/6)
回答No.5

WM_ERASEBKGND メッセージはつぶせませんが、ウィンドウの背景ブラシをなし (NULL) にすれば、WM_ERASEBKGND によるちらつきを抑えることができます。 また、テキストを書くときには ExtTextOut() などを使用して文字と背景色を一度に書いた方が良いと思います。 なお、背景色を無効化していますので、テキストがない領域については本来の背景色で塗りつぶす必要があることをお忘れなく。

milkoX
質問者

お礼

ありがとうございます。 > なお、背景色を無効化していますので、テキストがない領域については本来の背景色で塗りつぶす必要があることをお忘れなく。 試したことがありますが、結局自分で塗りつぶすことになりますので、 ちらつきました。 またなにかありましたらお願いします。 結局正しくダブルバッファを使うしかないような 気もしてきました。。

noname#30727
noname#30727
回答No.4

#3です。 少々追加します。 ダブルバッファリングというのは、描画用と表示用の2枚のビットマップを交互に使用する事を指します。 WindowsのGDIでこういった事を必要とするケースは、WM_PAINTで表示用のビットマップを描画している最中に、別のスレッドが描画用のビットマップに描画する事がある場合です。それ以外ではビットマップは1枚で足りますので、ダブルバッファリングは不要です。 もし、バッファとなるビットマップを毎回作成しているのであれば、最初に1回だけ作成するようにすれば、多少は改善されるかもしれません。

milkoX
質問者

お礼

度々ありがとうございます。 > もし、バッファとなるビットマップを毎回作成しているのであれば、最初に1回だけ作成するようにすれば、多少は改善されるかもしれません。 以前に試してましたが、変わりませんでした。 それと一回のみ作成だと毎回ビットマップをクリアする処理が必要になるので、それはそれで時間がかかりそうです。 また何かありましたらお願いします。

noname#30727
noname#30727
回答No.3

>WM_ERASEBKGNDメッセージをつぶせない仕様ですので、 これがある限り、どんな方法を使っても、ちらつきを抑える事は出来ません。 WM_ERASEBKGNDを受けとる必要があるのはわかりますが、何も描画しなければ受け取らなかったのと同じです。(文字を描画する部分だけ消さないという方法もありますが) それすらも仕様だから出来ないという事なら、ちらつくのも仕様だとするしかないです。 >ちらつきが抑えられましたが、極端に遅くなってしまいました。 ちらつきが抑えられたように見えるのは、極端に遅くなったからではないでしょうか。 10倍くらい遅くなったのなら、やってはいけない事をやっているのだろうと思いますが、2倍くらい遅くなったのであれば、改善できない可能性はあります。

milkoX
質問者

お礼

ありがとうございます。 > >WM_ERASEBKGNDメッセージをつぶせない仕様ですので、 > これがある限り、どんな方法を使っても、ちらつきを抑える事は出来ません。 確かにおっしゃるとおりです。 しかしファイルの内容をWindowに描画してますので、 スクロールなどによって文字が変わりますので、 一旦すべて消さないと全部重なって出て来てしまいます。 > 10倍くらい遅くなったのなら、やってはいけない事をやっているのだろうと思いますが、2倍くらい遅くなったのであれば、改善できない可能性はあります。 おかしいことをしているに違いないです。 ですが、どこがどうなのかが。。。 描画がロジックは全く同じで違いは描画先が BeginPaintで取得してDCか CreateCompatibleDCで作成したビットマップに関連付けられたDCかです。 同じロジックでも後者に対する描画は遅くなるということかもしれません。正しい知識があれば、判断ができますが、私では力不足です。知識を借りに来ました。

noname#16765
noname#16765
回答No.2

「ちらつく=なんども書かれている」で、 ダブルバッファリング(私はどんなものか知らない)が ただ書き込み処理速度を遅くしただけなのでちらつきが減ったけど根本的な解決になっていない。 という安楽的な考えじゃ答えは出ませんね。 すみません、ギブです。

noname#16765
noname#16765
回答No.1

こういったものが私は苦手なんですが、 これと似たようなものですかね?

参考URL:
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1780918
milkoX
質問者

補足

ありがとうございます。 同じようなものですね。 ビットマップ作成 ↓ ビットマップに描画 ↓ ビットマップを画面にコピー というだけの作業ですが、どこで遅くなったのが よくわからないです。。。

関連するQ&A