コントロールの描画の最適化
コンテナーが指定されたデバイス コンテキストに、自身を描画するようにコントロールに指示するとデバイス コンテキストには、 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);
}
}