共用方式為


最佳化控制項繪圖

當指示控制項將其本身拉入到容器提供的裝置內容中時,它通常會選取 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 傳回時讓它們保持選入裝置內容中,就不應該予以刪除。

若要防止 CPen CBrush 物件在完成時 OnDraw 被終結,請將它們儲存在成員變數中,而不是區域變數。 在控制項的類別宣告中,加入兩個新成員變數的宣告:

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 時建立畫筆和筆刷。 速度的提升則會以維護其他執行個體資料的成本為代價。

如果 ForeColor 或 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);
   }
}

另請參閱

MFC ActiveX 控制項:最佳化
COleControl 類別
MFC ActiveX 控制項
MFC ActiveX 控制項精靈
MFC ActiveX 控制項:繪製 ActiveX 控制項