[MFC] Ce este un control custom-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 custom-draw?

Post by Ovidiu Cucu » 28 Sep 2011, 12:22

Intrebare
Ce este un control custom-draw?

Raspuns
Pentru anumite controale Windows, sistemul trimite notificarea NM_CUSTOMDRAW (via WM_NOTIFY) atunci cand trebuie sa deseneze in el.
Daca tratam aceasta notificare in fereastra (dialogul) parinte sau tratam mesajul reflectat in clasa MFC a controlului, putem schimba desenarea default (de exemplu, schimba culoarea textului) si/sau face desenari suplimentare. Spunem ca implementam un control custom-draw.

Exemplu
Exemplul urmator arata un control listview report-style care are liniile in culori alternative si un anumit subitem incadrat intr-un dreptunghi.
Custom-draw List.jpg
Custom-draw List.jpg (28.87 KiB) Viewed 3630 times

Code: Select all

// CustomListCtrl.h

class CCustomListCtrl : public CListCtrl
{
   // ...
   DECLARE_MESSAGE_MAP()
   afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);
private:
   void _HandleSubitemPrePaint(LPNMLVCUSTOMDRAW pNMCD);
   void _HandleSubitemPostPaint(LPNMLVCUSTOMDRAW pNMCD);
};

Code: Select all

// CustomListCtrl.cpp
   // ...
   ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CCustomListCtrl::OnNMCustomdraw)
END_MESSAGE_MAP()

void CCustomListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
   LPNMLVCUSTOMDRAW pNMCD = (LPNMLVCUSTOMDRAW)pNMHDR;
   *pResult = CDRF_DODEFAULT;
   
   switch(pNMCD->nmcd.dwDrawStage)
   {
   case CDDS_PREPAINT:
      *pResult |= CDRF_NOTIFYITEMDRAW; // request item draw notify 
      break;
   case CDDS_ITEMPREPAINT:
      *pResult |= CDRF_NOTIFYSUBITEMDRAW; // request sub-item draw notify
      break;
   case CDDS_ITEMPREPAINT|CDDS_SUBITEM: // subitem pre-paint
      _HandleSubitemPrePaint(pNMCD);
      *pResult |= CDRF_NOTIFYPOSTPAINT; // request post-paint notify
      break;
   case CDDS_ITEMPOSTPAINT|CDDS_SUBITEM: // subitem post-paint
      _HandleSubitemPostPaint(pNMCD);
      break;
   }
}

Code: Select all

void CCustomListCtrl::_HandleSubitemPrePaint(LPNMLVCUSTOMDRAW pNMCD)
{
   // Note: for a listview, nmcd.dwItemSpec keeps the item index 
   const int nItem = (int)pNMCD->nmcd.dwItemSpec;
   if((nItem % 2) == 0)
   {
      // use custom colors
      pNMCD->clrText = RGB(255,255,255);
      pNMCD->clrTextBk = RGB(128,128,255);
   }
   else
   {
      // use default colors
      pNMCD->clrText = CLR_DEFAULT;
      pNMCD->clrTextBk = CLR_DEFAULT;
   }
}

Code: Select all

void CCustomListCtrl::_HandleSubitemPostPaint(LPNMLVCUSTOMDRAW pNMCD)
{
   const int nItem = (int)pNMCD->nmcd.dwItemSpec; 
   const int nSubItem = pNMCD->iSubItem;
   // Note: hard-coded values, just for the demo purpose
   if((22 == nItem) && (3 == nSubItem))
   {
      // Draw rectangle around subitem
      CRect rcSubItem;
      GetSubItemRect(nItem, pNMCD->iSubItem, LVIR_LABEL, rcSubItem);
      CDC* pDC = CDC::FromHandle(pNMCD->nmcd.hdc);
      CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
      CPen pen(PS_SOLID, 2, RGB(0,0,128));
      CPen* pOldPen = (CPen*)pDC->SelectObject(&pen);
      pDC->Rectangle(rcSubItem);
      pDC->SelectObject(pOldPen);
      pDC->SelectObject(pOldBrush);
   }
}
Resurse
<< Back to MFC index



Post Reply