Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CListCtrl: How to set each item's text background color individually?

5,034 views
Skip to first unread message

Khaled

unread,
Dec 31, 2000, 12:19:54 PM12/31/00
to
This is a very specific question that I didn't find an answer to in the
Microsoft Developer Network (MSDN). I need to set different text background
colors for different items in a list view control. The only function that
does this is CListCtrl::SetTextBkColor(COLORREF clr), but calling this
function sets the back color of all the items in the control, not individual
items.

I tried calling SetTextBkColor and then RedrawItems(first, last) to paint
specific items, it works, but if the control gets a paint message it redraws
all the items with the same color! I thought of overriding OnDraw to paint
each item with the color I want, but for some reason the framework doesn't
call the supplied CListView::OnDraw at all!!

I'm using VC++ 6.0, my project is an explorer style (CTreeView, CListView).
What I wanna do is something similar to the ACDSee image viewer file list
browser, where each file in the list view has a different text background
color.

I know it can be down without OwnerDraw, I used Spy++ to check the ListView
control styles of ACDSee and it didn't have the owner draw style set.

Thanks in advance,
please send a CC of ur reply to my email address,
Khaled


Mehdi Mousavi

unread,
Dec 31, 2000, 2:33:03 PM12/31/00
to
Custom draw, that's what you need. Lets see it how, though:

Add a message handler for the "NM_CUSTOMDRAW" message, so that you can get
the messages corrsponding to the custom drawing of the list. Lets name it
OnCustomDrawList:

void CMyTempView::OnCustomDrawList(NMHDR* pNMHDR, LRESULT* pResult )
{
NMLVCUSTOMDRAW* pLV = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);

*pResult = 0;

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

case CDDS_ITEMPREPAINT:
pLV->clrTextBk = RGB(255, 0, 0);
*pResult = CDRF_DODEFAULT;
break;
}
}


And finally, let me say that pLV->nmcd.dwItemSpec points to the item already
its going to be drawn. Do you processing on this item, and then change its
background color to whatever u would like. In the above example, I changed
it to the red color: RGB(255, 0, 0)

HTH,
Mehdi
--
Success is how high you bounce when you hit bottom!


"Khaled" <kha...@hotmail.com> wrote in message
news:_UJ36.189306$_5.42...@news4.rdc1.on.home.com...

Khaled

unread,
Dec 31, 2000, 3:00:48 PM12/31/00
to
Thanks a lot, I just found the same solution on www.codeguru.com, I knew
there's an easier way than owner draw :)

As the matter of fact this is exactly what I was looking for, and it makes
life a lot easier since I have access to the item's data where I store each
item's specific background color:

pLV->clrTextBk = GetItemData(pLV->ncmd.dwItemSpec);
or
pLV->clrTextBk = pLV->ncmd.lItemlParam;

Thanks,
Khaled

"Mehdi Mousavi" <webm...@modemmania.com> wrote in message
news:O#hOpC2cAHA.1360@tkmsftngp04...

jmc...@my-deja.com

unread,
Jan 22, 2001, 11:09:48 AM1/22/01
to
similarly, this is how you can change the font of
each item individually (here i've chenged the
font style to "italic", as a simple example):

// Since this is a CListCtrl-derivative, this
message map must exist:
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)

//...

void AGuiTableImp::OnCustomDraw(NMHDR* nmHdr,
LRESULT* result)
{
NMLVCUSTOMDRAW* customDrawItem =
reinterpret_cast<NMLVCUSTOMDRAW*>(nmHdr);

// Initialize to default processing:
*result = CDRF_DODEFAULT;

// If this is the prepaint stage, ask for
messages at each item-painting stage:
if (CDDS_PREPAINT == customDrawItem-
>nmcd.dwDrawStage)
{
*result = CDRF_NOTIFYITEMDRAW;
}
// If this is the item-prepainting stage,
change item display style if necessary:
else if (CDDS_ITEMPREPAINT == customDrawItem-
>nmcd.dwDrawStage)
{
// Get item's font:
HFONT realFont = HFONT(::SelectObject
(customDrawItem->nmcd.hdc,
HFONT(::GetStockObject(SYSTEM_FONT))));
LOGFONT logFont;
if (0 == ::GetObject(realFont, sizeof
(LOGFONT), &logFont))
// error

// Set item's font:
logFont.lfItalic = TRUE;
HFONT newFont = ::CreateFontIndirect
(&logFont);
if (NULL == ::SelectObject
(customDrawItem->nmcd.hdc, newFont))
// error
if (FALSE == ::DeleteObject(newFont))
// error

// Tell Windows to paint the control
itself, using the new font:
*result = CDRF_NEWFONT;
} // else
}

this works perfectly on NT and Win2K, as far as i
know. unfortunately, system crashes ensue on
Win95 Nd 98 IF the user attempts to resize
columns of the (report-view) list control to
widths beyond the boundaries of the control. the
font-changes discontinue registering and system
assertions and access violations fly. does
anyone have any recommendations on how to solve
this? i also tried an MFC-implementation,
recommended by Ben Burnett on codeguru.com, and
looked through
http://msdn.microsoft.com/library/psdk/shellcc/com
mctls/CustDraw/CustDraw.htm#CustomDraw_ChangingFon
tsAndColors, but found nothing pertaining to this
particular problem. help?


Sent via Deja.com
http://www.deja.com/

jmc...@my-deja.com

unread,
Jan 22, 2001, 12:03:29 PM1/22/01
to

> but found nothing pertaining to this
> particular problem. help?

got it. the secret was CDDS_ITEMPOSTPAINT. this is neglected in many
articles (including MS's) where custom-draw is treated. the article i
found most helpful was "Previewing the Common Controls DLL for
Microsoft Internet Exlorer 4.0, Part II" by Strohm Armstrong. in
short, CDDS_ITEMPOSTPAINT should be used to clean up if you did
a ::SelectObject() in item prepaint (or elsewhere). e.g.:
case CDDS_ITEMPOSTPAINT:
{
HFONT font = HFONT(::GetStockObject(DEFAULT_GUI_FONT));
font = HFONT(::SelectObject(customDrawItem->nmcd.hdc, font));
::DeleteObject(font);
*result = CDRF_DODEFAULT;
} // case

hope this is useful.

0 new messages