Friday, November 2, 2012

How to specify individual List item's Font color in VC++ WTL

To make a ListBox in WTL display colored texts you need to handle CustomDraw message.

Program to specify the color of individual list item according to some condition.


class CListViewCtrlEx: public  CWindowImpl<CListViewCtrlEx, CListViewCtrl>, public CCustomDraw<CListViewCtrlEx> 
CHAIN_MSG_MAP_ALT(CCustomDraw<CListViewCtrlEx>, 1)

LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL  bHandled);

 DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw);
 DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw);  
void ForceMeasureItemMessage();
void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/);
BOOL DeleteItem(int nItem);
void GetCellRect(int header_column, const CRect& item_rect, CRect& cell_rect);


LRESULT CListViewCtrlEx::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL  bHandled)
HDC hdc = (HDC)wParam;
RECT rcClient ;
HBRUSH hBkBrush = CreateSolidBrush(RGB(255,255,255));
FillRect(hdc, &rcClient, hBkBrush);
return 1;

DWORD CListViewCtrlEx::OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)

        return  CDRF_NOTIFYITEMDRAW;

DWORD CListViewCtrlEx::OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)

        NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( lpNMCustomDraw );

        COLORREF crText = RGB(0,0,0);

int itemid = (pLVCD->nmcd).dwItemSpec; //this is item id    

if(GetItemData(itemid) == 1)
crText = RGB(255,0,0);
crText = RGB(0,0,0);

        // Store the color back in the NMLVCUSTOMDRAW struct.

COLORREF crTextBk = RGB(255,255,255);
pLVCD->clrTextBk = crTextBk;
pLVCD->clrText = crText;
CDCHandle dc = pLVCD->nmcd.hdc;

        // Tell Windows to paint the control itself.
        return CDRF_DODEFAULT;

void CListViewCtrlEx::ForceMeasureItemMessage()

// I just want to nudge it up a little.
CRect window_rect;
CPoint pt = window_rect.TopLeft();
::ScreenToClient(GetParent(), &pt);
window_rect.right = pt.x + window_rect.Width();
window_rect.left = pt.x;
window_rect.bottom = pt.y + window_rect.Height(); = pt.y + 1;

// Alright now move it back. = pt.y;

void CListViewCtrlEx::DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/)


BOOL CListViewCtrlEx::DeleteItem(int nItem)

return (BOOL)::SendMessage(m_hWnd, LVM_DELETEITEM, nItem, 0L);

void CListViewCtrlEx::GetCellRect(int header_column, const CRect& item_rect, CRect& cell_rect)

CHeaderCtrl header = GetHeader();
CRect header_rect;
header.GetItemRect(header_column, &header_rect);

// If we don't do this, when we scroll to the right, we will be 

// drawing as if we weren't and your cells won't line up with the
// columns.
int x_offset = -GetScrollPos(SB_HORZ);
cell_rect.left = x_offset + header_rect.left;
cell_rect.right = x_offset + header_rect.right; =;
cell_rect.bottom = item_rect.bottom;

No comments:

Share at: