Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

Microsoft: Visual C++ FAQ

Programming

Colored entries in List Box
Posted: 14 Jun 02

Taken directly from MSDN -

============================================================

Ask Dr. GUI #43
November/December 1998

List Box, Draw Thyself
Dear Dr. GUI,
Please forgive me if I am suffering from amnesia and have already bugged you about this.... I remember I was going to send you e-mail, I just don't remember if I actually sent it. So on with my question...

I need to have individual lines inside a CListBox to possibly be different colors. I know that I can change the color for all of the text but that really doesn't help me that much. I have searched and searched for something that would help me do this and all I can find is how easy it is to do in Visual Basic. Is there any solution in VC++ that will give me this functionality?

Thanks!



Dr. GUI replies:

The good doctor notes that this won't be trivial, but your problem gives him a great chance to show how to use "owner-draw" list boxes. "Owner-draw" is a common Windows technique whereby Windows asks you to draw the item that needs to be drawn. Many Windows controls, including buttons and menus, also support owner-drawing.

So, for this example, we'll use an owner-drawn list box. The entire process involves just four simple steps:

Derive a class from CListBox.


Override the CListBox::MeasureItem virtual function to specify the height for each item.


Override the CListBox::DrawItem virtual function to perform the painting.


Override the CListBox::CompareItem virtual function to determine the order in which the a string has to be added. This is necessary only if you wish to have a sorted list.
Note that the list box should have the LBS_OWNERDRAWVARIABLE and LBS_HASSTRINGS styles set. You need to select these styles for the list box when you create it using a resource editor. Otherwise, if you create the list box dynamically, specify these styles during creation.

The following CLineListBox class provides an implementation. Here the color for the text is stored as item data and retrieved during painting. First, we implement the AddItem function, which adds the string to the list box and stores the color in the 32-bit item data associated with the string:

void CLineListBox::AddItem(const CString& str, COLORREF rgbText)
{
   int   nIndex;
   nIndex = AddString(str);
   if( CB_ERR != nIndex )
      SetItemData(nIndex, rgbText);
}
Next, we override DrawItem to draw the string in the color stored in the item data:

void CLineListBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
   CDC      dc;
   CRect      rcItem(lpDIS->rcItem);
   UINT      nIndex = lpDIS->itemID;
   COLORREF   rgbBkgnd = ::GetSysColor(
         (lpDIS->itemState & ODS_SELECTED) ?
               COLOR_HIGHLIGHT : COLOR_WINDOW);
   dc.Attach(lpDIS->hDC);
   CBrush br(rgbBkgnd);
   dc.FillRect(rcItem, &br);
   if( lpDIS->itemState & ODS_FOCUS )
      dc.DrawFocusRect(rcItem);
   if( nIndex != (UINT)-1 )
   {
      // The text color is stored as the item data.
      COLORREF   rgbText = (lpDIS->itemState & ODS_SELECTED) ?
            ::GetSysColor(COLOR_HIGHLIGHTTEXT) : GetItemData(nIndex);
      CString str;
      GetText(nIndex, str);
      dc.SetBkColor(rgbBkgnd);
      dc.SetTextColor(rgbText);
      dc.TextOut(rcItem.left + 2, rcItem.top + 2, str);
   }
   dc.Detach();
}
Then, we have to override MeasureItem to tell Windows how high each item is. (Note that the items could each be of different height if we wanted.)

void CLineListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
   // Set the item height. Get the DC, select the font for the
   // list box, and compute the average height.
   CClientDC   dc(this);
   TEXTMETRIC   tm;
   CFont* pFont = GetFont();
   CFont* pOldFont = dc.SelectObject(pFont);
   dc.GetTextMetrics(&tm);
   dc.SelectObject(pOldFont);
   lpMIS->itemHeight = tm.tmHeight + 4;   
}
Finally, we support sorting by overriding CompareItem:

int CLineListBox::CompareItem(LPCOMPAREITEMSTRUCT lpCIS)
{
   CString str1, str2;
   GetText(lpCIS->itemID1, str1);
   GetText(lpCIS->itemID2, str2);
   return str1.Compare(str2);
}
All that is needed to see the new list box in action is to create a variable of class CLineListBox, associate it with a list box window (perhaps using Class Wizard), and set the color for each text entered using SetItemData. If no color is specified for a string, it gets displayed in black when it is not selected. Suppose m_listBox is a variable of type, ClineListBox. In that case you may use:

   m_listBox.AddItem("Hello", RGB(255, 0, 0));  // Add string, "Hello", and display it in red.
   m_listBox.AddItem("Windows", RGB(255, 0, 255));  // Add string, "Windows", and display it in magenta.
   m_listBox.AddItem("Color listbox");      // Add string, "Color listbox", and display it in default black."

Back to Microsoft: Visual C++ FAQ Index
Back to Microsoft: Visual C++ Forum

My Archive

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close