[MFC] Ce este un control owner-draw?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Ce este un control owner-draw?

Post by Ovidiu Cucu » 04 Oct 2011, 12:16

Intrebare
Ce este un control owner-draw?

Raspuns
Un control owner-draw este un control pentru care intreaga responsabilitate a desenarii revine "owner-ului".
Mai bine zis, cel care implementeaza un control owner-draw, trebuie sa trateze mesajul WM_DRAWITEM in fereastra parinte si sa deseneze controlul.
In MFC, aceasta se poate face si in clasa controlului, suprascriind functia virtuala DrawItem (exemplu, CButton::DrawItem).
Pentru ca un control sa fie owner-draw trebuie ca sa aiba setat stilul corespunzator (exemplu, BS_OWNERDRAW pentru un buton).

Exemplu

Code: Select all

// OwnerdrawButton.h
// Simple ovner-draw button; just for DEMO purpose

class COwnerdrawButton : public CButton
{
   // ...
   virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
   // ...
private:
   void _DrawUpState(CDC* pDC, LPRECT lpRect);
   void _DrawDownState(CDC* pDC, LPRECT lpRect);
   void _DrawFocusedState(CDC* pDC, LPRECT lpRect);
   void _DrawDisabledState(CDC* pDC, LPRECT lpRect);
};

Code: Select all

// OwnerdrawButton.cpp

void COwnerdrawButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
{
   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
   UINT nState = lpDIS->itemState;
   if(nState & ODS_SELECTED)
   {
      // button is pushed
      _DrawDownState(pDC, &lpDIS->rcItem);
   }
   else if(nState & ODS_FOCUS)
   {
      // button has focus
      _DrawFocusedState(pDC, &lpDIS->rcItem);
   }
   else if(nState & ODS_DISABLED)
   {
      // button is disabled
      _DrawDisabledState(pDC, &lpDIS->rcItem);
   }
   else
   {
      // button is in "up" state (none of above)
      _DrawUpState(pDC, &lpDIS->rcItem);
   }
}

Code: Select all

void COwnerdrawButton::_DrawUpState(CDC* pDC, LPRECT lpRect)
{
   pDC->FillSolidRect(lpRect, ::GetSysColor(COLOR_BTNFACE));
   pDC->DrawEdge(lpRect, EDGE_ETCHED, BF_RECT);
   pDC->DrawText(_T("UP"), lpRect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}

Code: Select all

void COwnerdrawButton::_DrawDownState(CDC* pDC, LPRECT lpRect)
{
   pDC->FillSolidRect(lpRect, RGB(255,255,0));
   pDC->DrawEdge(lpRect, EDGE_SUNKEN, BF_RECT);
   pDC->DrawText(_T("DOWN"), lpRect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}

Code: Select all

void COwnerdrawButton::_DrawFocusedState(CDC* pDC, LPRECT lpRect)
{
   pDC->FillSolidRect(lpRect, RGB(255,0,0));
   pDC->DrawEdge(lpRect, EDGE_RAISED, BF_RECT);
   pDC->DrawText(_T("FOCUSED"), lpRect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}

Code: Select all

void COwnerdrawButton::_DrawDisabledState(CDC* pDC, LPRECT lpRect)
{
   pDC->FillSolidRect(lpRect, ::GetSysColor(COLOR_BTNFACE));
   pDC->DrawText(_T("DISABLED"), lpRect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
Note
  1. Controale precum combobox, listbox si listview pot fi owner-draw-fixed sau owner-draw-variable (exemplu, CBS_OWNERDRAWFIXED sau CBS_OWNERDRAWVARIABLE pentru combobox). Pentru cele owner-draw-variable se trimite mesajul WM_MEASUREITEM ce permte owner-ului sa indice dimensiunile unui item. In MFC, functia virtuala corespunzatoare din clasa controlului este MeasureItem.
  2. Pentru un combobox sau listbox owner-draw avand stilul CBS_SORT, respectiv LBS_SORT se trimite mesajul WM_COMPAREITEM ce permite owner-ului sa sorteze itemurile. In MFC se poate suprascrie in clasa controlului functia virtuala CompareItem.
  3. In practica, stilul owner-draw se aplica pentru customizarea controalelor simple (button, combobox, listbox). Pentru controalele mai complexe cum ar fi listview, se prefera custom-draw (se trateaza notificarea NM_CUSTOMDRAW).
  4. In biblioteca MFC exista clase care contin controale owner-draw. Exemple: CBitmapButton si CCheckListBox.
  5. In loc de owner-draw se foloseste si termenul self-draw (cand se suprascrie functia virtuala DrawItem din clasa controlului).
  6. Meniurile pot fi si ele owner-draw.
Resurse Vezi si
<< Back to MFC index



Post Reply