优化控件绘制

当控件将指示将引入所容器提供的设备上下文时,通常会选中 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 完成时,若要防止CPenCBrush 对象销毁,请将它们存储在成员变量而不是局部变量。 在控件的类声明中,将添加两个新成员变量声明:

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 后,此方法避免钢笔和画笔的创建。 速度改进是以维护的附加实例数据为代价。

如果更改前景色或背景色属性,钢笔或画笔需要重新创建。 为此,请重写和 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);
   }
}

请参见

参考

COleControl 类

MFC ActiveX 控件向导

概念

MFC ActiveX 控件:优化

MFC ActiveX 控件

MFC ActiveX 控件

MFC ActiveX 控件:绘制 ActiveX 控件