다음을 통해 공유


컨트롤 그리기 최적화

컨테이너 공급 디바이스 컨텍스트에 컨트롤을 그리게 되는 경우 일반적으로 디바이스 컨텍스트에 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에서 반환 시 선택한 해당 개체를 디바이스 컨텍스트에 남기려는 경우 삭제하지 않아야 합니다.

완료 시 CPenCBrush 개체가 제거 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 속성이 변경되는 경우 펜 또는 브러시를 다시 만들어야 합니다. 이렇게 하려면 OnForeColorChangedOnBackColorChanged 멤버 함수를 재정의합니다.

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 컨트롤 그리기