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.
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);
}
}
<< Back to MFC index