最佳化控制項繪圖
當指示控制項將其本身拉入到容器提供的裝置內容中時,它通常會選取 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 控制項