テクニカルレシピ(Visual C++のレシピ)

Home>>Visual C++>>再描画対応 LastUpdate:2009-01-21

View-Docを意識する

再描画を考えていないアプリは、
他のアプリと重なったとあとに、画面の一部が空白になってしまいます。

この問題を解決するには、下の3つの点に留意して下さい。
@表示に関するデータはメンバ変数にする
Aイベントハンドラ関数に描画処理を書かない(Invalidate/UpdateWindowでOnPaintを呼ぶだけ)
BOnPaintにあらゆる描画処理を書く
(ソースファイルはサンプルコードのtips2.zipにまとめてあります。)

上の3つは簡単に言えばDoc-Viewアーキテクチャを意識するということです。
データ処理と描画処理を分離し、描画関数はいつも同じ関数(OnPaint)で行います。

ダメアプリを知るに示したアプリの場合、
Startボタンのイベントハンドラ内に描画処理を記述しています。
このようにイベントハンドラに描画処理を記述してしまうと、
このイベントが呼ばれない限り描画が行われなくなってしまいます。

そこで上の3つの点に留意しながら、
前項で動的レイアウトの処理を追加したダメアプリをさらに改良してみます。

まずこのアプリの場合、
表示するデータは○と□の座標と、左上の進捗文字列です。
そこでそれぞれについて変数を設定します。

CString m_str; //進捗文字列
int m_rx[500]; //□のx座標
int m_ry[500]; //□のy座標
int m_ex[500]; //○のx座標
int m_ey[500]; //○のy座標

描画処理はOnPaintに集中させます。
OnPaintはダイアログベースの描画を扱う基本関数ですので、
再描画の際も常にこの関数が呼ばれるからです。

具体的にはelse以下(@以下)に、上記の変数の状態に合わせた描画処理を記述しています。
Aに注目してください。メンバ変数のm_strを見て描画の有無を判断しています。
つまりデータが入力されていればその内容が表示され、
データが入力されていなければ何も表示されないことになります。
これにより再描画の際もデータが入力されていれば適切な表示が行われることになります。

イベントハンドラ関数ではデータ処理だけさせています。
(描画命令を直接書いてはいけません。)
つまり先ほどの変数に○と□の座標、進捗文字列を設定し、
最後にInvalidateを使ってOnPaintを呼び出すだけです。

このようにデータ処理と描画処理を分離すると適切な再描画を行うことが出来ます。

動的レイアウト:前項<< ページの先頭に戻る >>次項:ちらつき防止


このエントリーをはてなブックマークに追加