If you do not want to go through the hassle implementing OwnerDraw list controls, where you got to code a bunch of stuff inside the DrawItem override, then you can use the CustomDraw handler. With version 4.70 of the Comctrl.dll, you can handle row data, but with the 4.72+ version of the Dll, you can handle cell data. Which opens a lot of possibilities.
Here I present some examples on how to use the CustomDraw message.
Note: Similar handling is also possible for the other common controls.
Add the following to your CListCtrl derived class header file:
Where GetCellRect is defined as follows:
afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);// add the following to your message map in the cpp file.
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)// add the following function to the cpp file.
// for specialized row handling.
// modify to suit. (in this sample function, I color every alternate row).
void CListCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
//for this notification, the structure is actually a
// NMLVCUSTOMDRAW that tells you what's going on with the custom
// draw action. So, we'll need to cast the generic pNMHDR pointer.
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW; // ask for item notifications.
break;case CDDS_ITEMPREPAINT:
*pResult = CDRF_DODEFAULT;int iRow = lplvcd->nmcd.dwItemSpec;
if(iRow & 1)
{
lplvcd->clrTextBk = RGB(255, 0, 0);
lplvcd->clrText = RGB(255, 255, 0);
*pResult = CDRF_NEWFONT;
}
break;default:
*pResult = CDRF_DODEFAULT;
}
}// add the following function to the cpp file.
// for specialized cell handling.
// modify to suit. (in this sample function, I color every alternate cell).
void CListCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
//for this notification, the structure is actually a
// NMLVCUSTOMDRAW that tells you what's going on with the custom
// draw action. So, we'll need to cast the generic pNMHDR pointer.
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW; // ask for subitem notifications.
break;case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW; // ask for subitem notifications.
break;case CDDS_ITEMPREPAINT|CDDS_SUBITEM: // recd when CDRF_NOTIFYSUBITEMDRAW is returned in
{ // response to CDDS_ITEMPREPAINT.
*pResult = CDRF_DODEFAULT;int iCol = lplvcd->iSubItem;
int iRow = lplvcd->nmcd.dwItemSpec;if((iRow & 1) && (iCol & 1))
{
lplvcd->clrTextBk = RGB(255, 0, 0);
lplvcd->clrText = RGB(255, 255, 0);
*pResult = CDRF_NEWFONT;
}
break;
}default:// it wasn't a notification that was interesting to us.
*pResult = CDRF_DODEFAULT;
}
}// add the following function to the cpp file.
// for specialized cell handling.
// modify to suit.
// (in this sample function, I color every alternate cell,
// if the checkbox style is not present, otherwise, I color all checked rows).
void CListCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
//for this notification, the structure is actually a
// NMLVCUSTOMDRAW that tells you what's going on with the custom
// draw action. So, we'll need to cast the generic pNMHDR pointer.
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW; // ask for subitem notifications.
break;case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW; // ask for subitem notifications.if(GetExtendedStyle() & LVS_EX_CHECKBOXES) // if we have a checkbox style,
{ // forget about subitem notifications.
*pResult = CDRF_DODEFAULT;int iRow = lplvcd->nmcd.dwItemSpec;
if(GetCheck(iRow)) // highlight checked rows
{
lplvcd->clrTextBk = RGB(255, 0, 0);
lplvcd->clrText = RGB(255, 255, 0);
*pResult = CDRF_NEWFONT;
}
}
break;case CDDS_ITEMPREPAINT|CDDS_SUBITEM: // recd when CDRF_NOTIFYSUBITEMDRAW is returned in
{ // response to CDDS_ITEMPREPAINT.
*pResult = CDRF_DODEFAULT;int iCol = lplvcd->iSubItem;
int iRow = lplvcd->nmcd.dwItemSpec;if((iRow & 1) && (iCol & 1))
{
lplvcd->clrTextBk = RGB(255, 0, 0);
lplvcd->clrText = RGB(255, 255, 0);
*pResult = CDRF_NEWFONT;
}
break;
}default:// it wasn't a notification that was interesting to us.
*pResult = CDRF_DODEFAULT;
}
}// add the following function to the cpp file.
// for specialized cell handling.
// modify to suit.
// (in this sample function, I display the text centered).
void CListCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
//for this notification, the structure is actually a
// NMLVCUSTOMDRAW that tells you what's going on with the custom
// draw action. So, we'll need to cast the generic pNMHDR pointer.
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;switch(lplvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW; // ask for subitem notifications.
break;case CDDS_ITEMPREPAINT:
*pResult = CDRF_NOTIFYSUBITEMDRAW;
break;case CDDS_ITEMPREPAINT|CDDS_SUBITEM:
{
int iCol = lplvcd->iSubItem;
int iRow = lplvcd->nmcd.dwItemSpec;
CString sItem = GetItemText(iRow, iCol);
CRect rc;
GetCellRect(iRow, iCol, LVIR_BOUNDS, rc);// get the device context.
CDC *pDC= CDC::FromHandle(lplvcd->nmcd.hdc);// paint the text centered.
pDC->DrawText(sItem , rc, DT_CENTER);*pResult= CDRF_SKIPDEFAULT;
break;
}default:// it wasn't a notification that was interesting to us.
*pResult = CDRF_DODEFAULT;
}
}
BOOL CListCtrlEx::GetCellRect(int iRow, int iCol, int nArea, CRect &rect)
{
if(iCol)
return GetSubItemRect(iRow, iCol, nArea, rect);if(GetColumnCount()== 1)
return GetItemRect(iRow, rect, nArea);iCol = 1;
CRect rCol1;
if(!GetSubItemRect(iRow, iCol, nArea, rCol1))
return FALSE;if(!GetItemRect(iRow, rect, nArea))
return FALSE;rect.right = rCol1.left;
return TRUE;
}
History
Date Posted: June 19, 1999