Question

I have ClistView control in my MFC application. I need to color some of the items according to its content. For example, if it begins with "No Response to", i need to make it red.

So far, i've tried

BEGIN_MESSAGE_MAP(CMessageView, CListView)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW,customDraw)
END_MESSAGE_MAP()

void CMessageView::Update()
{
CListCtrl& refCtrl = GetListCtrl();   
refCtrl.InsertItem(LVIF_TEXT|LVIF_PARAM,0,CTime::GetCurrentTime().Format("%H:%M:%S"),0,0,0,42);
refCtrl.SetItemText(0,1,"some text");
refCtrl.SetItemText(0,2,"No response to open");
}

void CMessageView::customDraw(NMHDR * pNMHDR, LRESULT * pResult)
{
_ASSERTE(*pResult == 0);

NMLVCUSTOMDRAW * pnmlvcd = (NMLVCUSTOMDRAW *)pNMHDR;

DWORD dwDrawStage = pnmlvcd->nmcd.dwDrawStage;

BOOL bSubItem = dwDrawStage & CDDS_SUBITEM;
dwDrawStage &= ~CDDS_SUBITEM;

switch (dwDrawStage)
{
case CDDS_PREPAINT:
    {
        *pResult = CDRF_NOTIFYITEMDRAW;
        break;
    }
case CDDS_ITEMPREPAINT:
case CDDS_SUBITEM:
    {
            if(pnmlvcd->nmcd.lItemlParam == 42)
            {
                pnmlvcd->clrText = RGB(255,0,0);            

            }               
            *pResult = 0;               
        break;
    }
default:
    {
        *pResult = 0;
        break;
    }
}
}

But it does not work. The color does not change. Am i missing something or doing something wrong?

Was it helpful?

Solution 2

This code in a simple example application worked for me. My list control has two columns and two items. The second item, second column has item data set to 42, in this case, only that particular subitem had the text changed to red.

void CMFCTestDlg::OnNMCustomdrawList1(NMHDR *pNMHDR, LRESULT *pResult)
{
   NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
   // TODO: Add your control notification handler code here

   *pResult = CDRF_DODEFAULT;

   switch(pLVCD->nmcd.dwDrawStage)
   {
   case CDDS_PREPAINT:
      *pResult = CDRF_NOTIFYITEMDRAW;
      break;

   case CDDS_ITEMPREPAINT:
      *pResult = CDRF_NOTIFYSUBITEMDRAW;
      break;

   case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
      {
         if(1 == pLVCD->iSubItem)
         {
            if(pLVCD->nmcd.lItemlParam == 42)
            {
               pLVCD->clrText = RGB(255, 0, 0);
            }
         }
      }
      break;
   }
}

OTHER TIPS

If you have VS2008 SP1, it's much easier to use CMFCListCtrl instead - it has virtual functions you can override to set the foreground and background colours of each row.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top