コントロールの描画の最適化
コンテナーが指定されたデバイス コンテキストに描画するようにコントロールに指示するとデバイス コンテキストには、GDI オブジェクト (ペン、ブラシやフォントなど) を選択し、描画操作の実行、および前の GDI オブジェクトを復元します。 コンテナーが描画に複数のコントロールを同じデバイス コンテキストが発生した場合は、各コントロールに必要な GDI オブジェクトを選択すると、時間をコントロールが、選択したオブジェクトを復元して保存できます。 すべてのコントロールは、描画、コンテナーは自動的に、元のオブジェクトを復元できます。
コンテナー サポートが、この方法は、コントロール COleControl::IsOptimizedDraw のメンバー関数を呼び出すことができるかどうかを確認する。 この関数の戻り値 TRUEコントロールが、選択したオブジェクトを復元することで既定の手順を省略できます。
OnDraw の次の (特に) 関数があるコントロールを検討する:
void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
CPen pen(PS_SOLID, 0, TranslateColor(GetForeColor()));
CBrush brush(TranslateColor(GetBackColor()));
CPen* pPenSave = pdc->SelectObject(&pen);
CBrush* pBrushSave = pdc->SelectObject(&brush);
pdc->Rectangle(rcBounds);
pdc->SelectObject(pPenSave);
pdc->SelectObject(pBrushSave);
}
この例のペンとブラシを意味するローカル変数 (OnDraw 関数が終了すると、スコープの外に出たときにデストラクターを呼び出すことができます。 デストラクターは、対応する GDI オブジェクトを削除します。 ただし、これらを使用 OnDrawから戻るときにデバイス コンテキストに選択する場合は削除しないでください。
OnDraw が終了したら CPen と CBrush オブジェクトを格納し、ローカル変数ではなく、メンバー変数で破棄されるのを防ぐには、 コントロールのクラス宣言では、2 種類の新しいメンバー変数の宣言を追加する:
class CMyAxOptCtrl : public COleControl
{
...
CPen m_pen;
CBrush m_brush;
};
次に、OnDraw 関数は次のように書き換えることができます。:
void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
CPen pen(PS_SOLID, 0, TranslateColor(GetForeColor()));
CBrush brush(TranslateColor(GetBackColor()));
CPen* pPenSave = pdc->SelectObject(&pen);
CBrush* pBrushSave = pdc->SelectObject(&brush);
pdc->Rectangle(rcBounds);
pdc->SelectObject(pPenSave);
pdc->SelectObject(pBrushSave);
}
この方法は OnDraw が呼び出されたときにペンとブラシの作成を回避できます。 速度が向上は追加インスタンス データを保持する損なわれます。
前景色または BackColor プロパティの変更、ペンまたはブラシを再作成する必要がある場合。 これを行うには、OnForeColorChanged と OnBackColorChanged のメンバー関数をオーバーライドする:
void CMyAxOptCtrl::OnForeColorChanged()
{
m_pen.DeleteObject();
}
void CMyAxOptCtrl::OnBackColorChanged()
{
m_brush.DeleteObject();
}
次のように、最後に SelectObject の不要な呼び出しを削除するには、OnDraw を変更する:
void CMyAxOptCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
if (m_pen.m_hObject == NULL)
m_pen.CreatePen(PS_SOLID, 0, TranslateColor(GetForeColor()));
if (m_brush.m_hObject == NULL)
m_brush.CreateSolidBrush(TranslateColor(GetBackColor()));
CPen* pPenSave = pdc->SelectObject(&m_pen);
CBrush* pBrushSave = pdc->SelectObject(&m_brush);
pdc->Rectangle(rcBounds);
if (! IsOptimizedDraw())
{
pdc->SelectObject(pPenSave);
pdc->SelectObject(pBrushSave);
}
}