次の方法で共有


MFC ActiveX コントロール : ActiveX コントロールの描画

ここでは、ActiveX コントロールの描画プロセスと、コードを変更して描画プロセスを最適化する方法について説明します。 前に選択された GDI オブジェクトをコントロールが個別に復元しないようにすることによって描画を最適化する方法については、「コントロールの描画の最適化」を参照してください。 この場合は、すべてのコントロールの描画が終了すると、コンテナーによって元のオブジェクトが自動的に復元されます。

ここでは、MFC ActiveX コントロール ウィザードの既定の設定で作成されるコントロールを例として使用します。 MFC ActiveX コントロール ウィザードを使ってスケルトン コントロール アプリケーションを作成する方法については、「MFC ActiveX コントロール ウィザード」を参照してください。

以下の内容について説明します。

  • コントロールの描画プロセスと描画をサポートするために ActiveX コントロール ウィザードが作成するコード

  • 描画プロセスを最適化する方法

  • メタファイルを使ってコントロールを描画する方法

ActiveX コントロールの描画プロセス

ActiveX コントロールが最初に表示されますまたは再描画されるときは、彼らと同様に他のアプリケーションを 1 つの重要な違いと MFC を使用して開発の描画プロセスを実行します。ActiveX コントロールをアクティブまたは非アクティブな状態にすることができます。

アクティブなコントロールは、ActiveX コントロール コンテナーに子ウィンドウとして表示されます。 また、その他のウィンドウと同様に、WM_PAINT メッセージを受け取ると自身を描画します。 このメッセージは、コントロールの基本クラスである COleControl によって、OnPaint 関数で処理されます。 既定の実装では、コントロールの OnDraw 関数が呼び出されます。

アクティブでないコントロールでは、描画方法が異なります。 コントロールがアクティブでない場合、コントロールのウィンドウは表示されていないかまたは存在しないため、描画メッセージを受け取ることができません。 このため、代わりにコントロール コンテナーが直接コントロールの OnDraw 関数を呼び出します。 このプロセスは、OnPaint メンバー関数が呼び出されないという点で、アクティブなコントロールの描画プロセスとは異なります。

このように、ActiveX コントロールの更新方法は、コントロールの状態によって異なります。 ただし、OnDraw メンバー関数はいずれの場合にも呼び出されるため、通常は描画コードの大半をこのメンバー関数内で記述します。

OnDraw メンバー関数は、コントロールの描画を処理します。 コントロールがアクティブでない場合は、コントロール コンテナーが、コントロール コンテナーのデバイス コンテキストとコントロールが占めている四角形領域の座標を引数として、OnDraw を呼び出します。

フレームワークによって OnDraw メンバー関数に渡される四角形には、コントロールが占めている領域が含まれています。 コントロールがアクティブな場合、左上隅の座標は (0, 0) になり、コントロールを格納している子ウィンドウのデバイス コンテキストが渡されます。 コントロールがアクティブでない場合、左上隅の座標は (0, 0) になるとは限りません。また、渡されるデバイス コンテキストは、そのコントロールがあるコントロール コンテナーのデバイス コンテキストになります。

注意

OnDraw を変更する場合は、四角形の左上隅が常に (0, 0) とは限らないことに注意しておく必要があります。また、描画は、OnDraw に渡される四角形の中だけで行うようにしてください。 四角形の領域外に描画すると、予想外の結果になる可能性があります。

MFC ActiveX コントロール ウィザードによってコントロールの実装ファイル (.CPP) に記述される既定の実装を次に示します。白いブラシで四角形が描画され、現在の背景色で楕円が塗りつぶされます。

void CMyAxUICtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
   if (!pdc)
      return;

   // TODO: Replace the following code with your own drawing code.
   pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
   pdc->Ellipse(rcBounds);
}

注意

コントロールを描画するときは、OnDraw 関数にパラメーター pdc として渡されるデバイス コンテキストの状態を考慮に入れないでください。 デバイス コンテキストは、コンテナー アプリケーションによって提供される場合もあるため、必ずしも既定の状態に初期化されるとは限りません。 特に、描画コードが依存するペン、ブラシ、色、フォントなどのリソースは明示的に選択するようにしてください。

描画コードの最適化

コントロールの自己描画が正しく行われるようになったら、次に OnDraw 関数を最適化します。

ActiveX コントロールの既定の描画では、コントロール領域全体が描画されます。 単純なコントロールではこのままでも問題ありませんが、通常は、コントロール全体を描画するよりも、更新が必要な部分だけを再描画する方が時間を短縮できます。

OnDraw 関数の描画動作は、再描画が必要な四角形の領域を rcInvalid として渡すだけで、簡単に最適化できます。 この領域は、通常コントロール領域全体より小さくなるため、描画プロセスが高速化されます。

メタファイルを使ったコントロールの描画

OnDraw 関数のパラメーター pdc は、ほとんどの場合、画面のデバイス コンテキスト (DC: device context) を指します。 ただし、コントロールのイメージを印刷する場合や、印刷プレビュー セッションの間などには、"メタファイル DC" と呼ばれる特別な種類の DC が描画のために渡されます。 画面 DC では、受信した要求はすぐに処理されますが、メタファイル DC では後で再生するために格納されます。 一部のコンテナー アプリケーションでも、デザイン モードでメタファイル DC を使ってコントロール イメージを描画します。

メタファイルの描画要求コンテナー 2 つのインターフェイスの機能を行うことができます。IViewObject::Draw (この関数非描画メタファイルを呼び出すこともできます)、 :getdata。 パラメーターの 1 つとしてメタファイル DC を渡すと、MFC フレームワークによって COleControl::OnDrawMetafile が呼び出されます。 これは仮想メンバー関数であるため、特別な処理を行うには、コントロール クラスでオーバーライドします。 既定の動作では、COleControl::OnDraw が呼び出されます。

コントロールを画面デバイス コンテキストとメタファイル デバイス コンテキストの両方で描画できるようにするには、両方のデバイス コンテキストでサポートされているメンバー関数だけを使用します。 また、座標系がピクセル単位でないことも必要です。

OnDrawMetafile の既定の実装では、コントロールの OnDraw 関数が呼び出されます。OnDrawMetafile をオーバーライドしない場合は、メタファイル デバイス コンテキストと画面デバイス コンテキストの両方に対応したメンバー関数だけを使用するようにしてください。 次の表は、メタファイル デバイス コンテキストと画面デバイス コンテキストの両方で使用できる CDC のメンバー関数の一覧です。 これらの関数の詳細については、『MFC リファレンス』の「CDC」クラスを参照してください。

Arc

BibBlt

Chord

Ellipse

エスケープ特殊文字

ExcludeClipRect

ExtTextOut

FloodFill

IntersectClipRect

LineTo

MoveTo

OffsetClipRgn

OffsetViewportOrg

OffsetWindowOrg

PatBlt

Pie

Polygon

Polyline

PolyPolygon

RealizePalette

RestoreDC

RoundRect

SaveDC

ScaleViewportExt

ScaleWindowExt

SelectClipRgn

SelectObject

SelectPalette

SetBkColor

SetBkMode

SetMapMode

SetMapperFlags

SetPixel

SetPolyFillMode

SetROP2

SetStretchBltMode

SetTextColor

SetTextJustification

SetViewportExt

SetViewportOrg

SetWindowExt

SetWindowORg

StretchBlt

TextOut

 

CDC のメンバー関数のほかにも、メタファイル DC に対応している関数がいくつかあります。 これらを含めるCPalette::AnimatePaletteCFont::CreateFontIndirect、および 3 つのメンバー関数のCBrush:使う、および CreatePatternBrush

メタファイルに記録されている関数です。DrawFocusRectDrawIconDrawTextExcludeUpdateRgnFillRectFrameRectGrayStringInvertRectScrollDC、および TabbedTextOut。 メタファイル DC は、実ときにデバイスに関連付けられているわけではないので、SetDIBitsGetDIBits、および CreateDIBitmap では使用できません。 SetDIBitsToDevice および StretchDIBits では、出力先としてメタファイル DC を使用できます。 CreateCompatibleDCCreateCompatibleBitmap、および CreateDiscardableBitmap では、メタファイル DC を使ってもあまり意味がありません。

メタファイル DC を使用するときは、ピクセル単位の座標系は使えません。 このため、パラメーター rcBounds で OnDraw に渡される四角形に合わせて、描画コード全体を調整する必要があります。 rcBounds はコントロールのウィンドウのサイズを表すため、コントロールの領域外の描画を防ぐことができます。

コントロールのメタファイル描画を実装した後に、テスト コンテナーを使ってメタファイルをテストします。 テスト コンテナーへのアクセス方法については、「テスト コンテナーでのプロパティとイベントのテスト」を参照してください。

テスト コンテナーを使ってコントロールのメタファイルをテストするには

  1. テスト コンテナーの [編集] メニューの [新しいコントロールを挿入] をクリックします。

  2. [新しいコントロールを挿入] ボックスでコントロールを選択し、[OK] をクリックします。

    コントロールがテスト コンテナーに表示されます。

  3. [コントロール] メニューの [メタファイルの描画] をクリックします。

    別のウィンドウにメタファイルが表示されます。 このウィンドウのサイズを変更すると、拡大縮小がコントロールのメタファイルにどのように影響するのかを確認できます。 このウィンドウはいつでも閉じることができます。

参照

概念

MFC ActiveX コントロール