ビューの描画
更新 : 2007 年 11 月
アプリケーションのほとんどすべての描画はビューの OnDraw メンバ関数で発生するため、ビュー クラスでオーバーライドする必要があります。ただし、「ビューを経由したユーザー入力の解釈」で説明されているマウス描画は例外です。OnDraw のオーバーライド関数では、次の処理を行います。
自分で用意したドキュメント メンバ関数を呼び出してデータを取得します。
フレームワークが OnDraw に渡すデバイス コンテキスト オブジェクトのメンバ関数を呼び出して、データを表示します。
ドキュメントのデータが変更されたときは、その変更を反映するためにビューを再描画する必要があります。一般に、ユーザーがドキュメントのビュー経由で変更を加えると、再描画が必要になります。この場合、ビューはドキュメントの UpdateAllViews メンバ関数を呼び出して、同じドキュメントのすべてのビューに対して、自分自身を更新するように通知します。UpdateAllViews は、各ビューの OnUpdate メンバ関数を呼び出します。OnUpdate の既定の実装は、ビューのクライアント領域全体を無効化します。ドキュメントの変更部分に割り当てられたクライアント領域だけを無効化するために、この関数をオーバーライドすることもできます。
CDocument クラスの UpdateAllViews メンバ関数と、CView クラスの OnUpdate メンバ関数で、ドキュメントの変更箇所を記述した情報を渡すことができます。この "ヒント" 機構を使うと、ビューの再描画領域を限定できます。OnUpdate は 2 つの "ヒント" 引数を受け取ります。1 番目の lHint は LPARAM 型なので、必要に応じて任意のデータを渡します。2 番目の pHint は CObject* 型なので、CObject から派生した任意のオブジェクトへのポインタを渡します。
ビューが無効になると、Windows はそのビューに WM_PAINT メッセージを送ります。ビューの OnPaint ハンドラ関数は、CPaintDC クラスのデバイス コンテキスト オブジェクトを作成してメッセージに応答し、ビューの OnDraw メンバ関数を呼び出します。通常、OnPaint ハンドラ関数をオーバーライドする必要はありません。
デバイス コンテキストとは、ディスプレイやプリンタなどのデバイスの描画属性についての情報を保持している Windows のデータ構造体のことです。すべての描画呼び出しは、デバイス コンテキスト オブジェクトを経由して行われます。画面に描画する場合、OnDraw は CPaintDC オブジェクトに渡されます。プリンタに描画する場合、OnDraw は現在のプリンタとして設定されている CDC オブジェクトに渡されます。
ビューで描画を行うためのコードでは、まずドキュメントへのポインタを取得し、それからデバイス コンテキスト経由で描画呼び出しを行います。その描画処理を示す簡単な OnDraw の例は次のとおりです。
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CString s = pDoc->GetData(); // Returns a CString
CRect rect;
GetClientRect(&rect);
pDC->SetTextAlign(TA_BASELINE | TA_CENTER);
pDC->TextOut(rect.right / 2, rect.bottom / 2, s, s.GetLength());
}
この例では、派生したドキュメント クラスのメンバ関数として GetData 関数を定義します。
例では、ドキュメントから取得した文字列をビューの中央に配置して表示します。画面描画用に OnDraw を呼び出す場合、pDC で渡される CDC オブジェクトは CPaintDC です。このとき既に、CPaintDC のコンストラクタは、BeginPaint を呼び出しています。描画関数の呼び出しは、デバイス コンテキスト ポインタを経由して行われます。デバイス コンテキストと描画呼び出しの詳細については、『MFC リファレンス』の CDC クラスに関するトピック、および「ウィンドウ オブジェクトの操作」を参照してください。
OnDraw を記述する方法の例については、「MFC サンプル」を参照してください。