Ask a questionAsk a question
 

AnswerSelection Color in ListView win32API (C++)

  • Monday, August 17, 2009 6:55 AMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hi,

    Can anyone show me, how to change selection color in a ListView?

    I've resolved this problem, but only partially. Here is the code example in c++:

    //ListView is my own class
    void ListView::SetSelectionColor(COLORREF BkColor, COLORREF TextColor)
    {
    	int elements[2] = {COLOR_HIGHLIGHT,COLOR_HIGHLIGHTTEXT};
    	DWORD newColors[2];
    
    	oldSelColors[0] = GetSysColor(elements[0]);
    	oldSelColors[1] = GetSysColor(elements[1]);
    
    	newColors[0] = BkColor;
    	newColors[1] = TextColor;
    
    	SetSysColors(2,elements,newColors); //changes system colors:
    //COLOR_HIGHLIGHT : bkcolor of selected item in listview
    //COLOR_HIGHLIGHTTEXT : textcolor of selected item in listview
    }
    


    This resolution works, but unfortunately it additionally changes selection colors everywhere, because that ugly function sends WM_SYSCOLORCHANGE message to all windows (or everywhere, where 'she'[it has to be woman ;P] can 'scream')!
    (I am thinking, if I knew the SetSysColors full implementation, I'd help quite good to myself... ;P)

    The point is: how to make things right to change selection color only in ListView control?
    Please, oh Please, help me!

Answers

  • Wednesday, August 19, 2009 9:26 PMTiKu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    You might be right. I use custom draw to give alternating lines a different background color in details view. The code doesn't distinguish between selected items and normal items, yet selected items get the system's default background. Nevertheless the article you've linked, is wrong.

    One thing you could try: On CDDS_ITEMPREPAINT draw your own selection rectangle, call SetBkColor with the color you want to use and SetBkMode(OPAQUE) and return CDRF_DODEFAULT.
    If this doesn't work, you could still use custom draw to achieve what you want. But you would have to draw the selected item entirely yourself then (and return CDRF_SKIPDEFAULT). For Small Icon and List view, drawing an item yourself isn't that hard. For Details view it's a bit harder, but doable. I'm not sure about Icons view (putting everything at the correct position could become nasty). Tiles view would definitly be painful.
    Windows 7 would be much better without DRM and Product Activation ;) (No, I'm no software pirate)
    • Marked As Answer byNorethel Friday, August 21, 2009 11:51 AM
    •  
  • Friday, August 21, 2009 11:51 AMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    I resolved the problem! TiKu, You didn't help me directly, but Your advice made some idea to born in my mind, and for this I'll give You positive note :) Here is the resolution:

    case CDDS_ITEMPREPAINT:
    		{
    			if (ListView_GetItemState(hListView,lplvcd->nmcd.dwItemSpec,LVIS_FOCUSED|LVIS_SELECTED) == (LVIS_FOCUSED|LVIS_SELECTED))
    			{
    				RECT textRect;
    				wchar_t iSubTxt1[64];
    				wchar_t iSubTxt2[64];
    				HFONT oldFont, newFont;
    
    				ListView_GetItemRect(hListView,lplvcd->nmcd.dwItemSpec,&ItemRect,LVIR_BOUNDS);
    				bgRgn = CreateRectRgnIndirect(&ItemRect);
    				MyBrush = CreateSolidBrush(RGB(100,100,100));
    				FillRgn(lplvcd->nmcd.hdc, bgRgn, MyBrush);
    				DeleteObject(MyBrush);
    
    				SetTextColor(lplvcd->nmcd.hdc, RGB(255,255,255));
    
    				newFont = CreateFont(16, 0, 0, 0, FW_NORMAL, TRUE, FALSE, FALSE,
    										EASTEUROPE_CHARSET, 0, 0, CLEARTYPE_NATURAL_QUALITY,
    										DEFAULT_PITCH | FF_DONTCARE, L"Times New Roman");
    				oldFont = (HFONT)SelectObject(lplvcd->nmcd.hdc,newFont);
    
    				ListView_GetItemText(hListView,lplvcd->nmcd.dwItemSpec,0,iSubTxt1,64);
    				SetRect(&textRect, ItemRect.left+5,ItemRect.top, ItemRect.right, ItemRect.bottom);
    				DrawText(lplvcd->nmcd.hdc,iSubTxt1,-1,&textRect, DT_LEFT | DT_NOCLIP);
    				ListView_GetItemText(hListView,lplvcd->nmcd.dwItemSpec,1,iSubTxt2,64);
    				SetRect(&textRect, ItemRect.left+Width/3+5,ItemRect.top, ItemRect.right, ItemRect.bottom);
    				DrawText(lplvcd->nmcd.hdc,iSubTxt2,-1,&textRect, DT_LEFT | DT_NOCLIP);
    
    				SelectObject(lplvcd->nmcd.hdc,oldFont);
    				DeleteObject(newFont);
    
    				return CDRF_SKIPDEFAULT;
    			}
    

    Does having an audience for Your sins make You feel like You're special? Does it make You proud?
    • Marked As Answer byNorethel Friday, August 21, 2009 11:51 AM
    •  

All Replies

  • Monday, August 17, 2009 7:36 AMTiKu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    What else do you expect from a function called SetSys Colors? ;)
    Use custom draw to change the color in a single list view control. http://msdn.microsoft.com/en-us/library/bb774865.aspx
    Windows 7 would be much better without DRM and Product Activation ;) (No, I'm no software pirate)
  • Monday, August 17, 2009 11:20 AMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    God, please, give me strange!

    'Custom draw does not allow you to change the font attributes for selected items.' -> http://msdn.microsoft.com/en-us/library/bb761817%28VS.85%29.aspx

    Any more funny ideas...? ;)

    p.s. If it's so simple, I'd never ask You and wouldn't waste my precious time signing in at this odd forum :)

    Does having an audience for Your sins make You feel like You're special? Does it make You proud?
    • Edited byNorethel Monday, August 17, 2009 8:40 PM
    • Edited byNorethel Monday, August 17, 2009 11:36 AM
    •  
  • Tuesday, August 18, 2009 5:35 PMTiKu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks for your friendly words.

    First, your question was about changing colors. The article is about changing fonts.
    Second, the article is wrong. Changing the font of selected items using custom draw works well for me.

    Windows 7 would be much better without DRM and Product Activation ;) (No, I'm no software pirate)
  • Wednesday, August 19, 2009 7:33 PMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    1. Be my guest ;P

    The rest:

    You don't understand me:

    Changing colors of item's or subitem's background or text works fine in Custom draw, but: try to change color of SELECTED item by this f...... Custom Draw and tell me if it works. If You will do this and show me how-to-do in your c++ example: You're God for me, and if You're woman: I'll give You my phone number ;P

    p.s. remember, that I'm asking about the way to do this in Win32Api !
    Does having an audience for Your sins make You feel like You're special? Does it make You proud?
  • Wednesday, August 19, 2009 9:26 PMTiKu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    You might be right. I use custom draw to give alternating lines a different background color in details view. The code doesn't distinguish between selected items and normal items, yet selected items get the system's default background. Nevertheless the article you've linked, is wrong.

    One thing you could try: On CDDS_ITEMPREPAINT draw your own selection rectangle, call SetBkColor with the color you want to use and SetBkMode(OPAQUE) and return CDRF_DODEFAULT.
    If this doesn't work, you could still use custom draw to achieve what you want. But you would have to draw the selected item entirely yourself then (and return CDRF_SKIPDEFAULT). For Small Icon and List view, drawing an item yourself isn't that hard. For Details view it's a bit harder, but doable. I'm not sure about Icons view (putting everything at the correct position could become nasty). Tiles view would definitly be painful.
    Windows 7 would be much better without DRM and Product Activation ;) (No, I'm no software pirate)
    • Marked As Answer byNorethel Friday, August 21, 2009 11:51 AM
    •  
  • Wednesday, August 19, 2009 9:29 PMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I'll try and then give You my results, so... We're 'in touch' :)
    Does having an audience for Your sins make You feel like You're special? Does it make You proud?
  • Thursday, August 20, 2009 11:40 AMcarly3 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    It's an old Win32 FAQ (90's..)
    You can ask on Win32 ng for usual methods ( in C mainly)
  • Friday, August 21, 2009 11:51 AMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    I resolved the problem! TiKu, You didn't help me directly, but Your advice made some idea to born in my mind, and for this I'll give You positive note :) Here is the resolution:

    case CDDS_ITEMPREPAINT:
    		{
    			if (ListView_GetItemState(hListView,lplvcd->nmcd.dwItemSpec,LVIS_FOCUSED|LVIS_SELECTED) == (LVIS_FOCUSED|LVIS_SELECTED))
    			{
    				RECT textRect;
    				wchar_t iSubTxt1[64];
    				wchar_t iSubTxt2[64];
    				HFONT oldFont, newFont;
    
    				ListView_GetItemRect(hListView,lplvcd->nmcd.dwItemSpec,&ItemRect,LVIR_BOUNDS);
    				bgRgn = CreateRectRgnIndirect(&ItemRect);
    				MyBrush = CreateSolidBrush(RGB(100,100,100));
    				FillRgn(lplvcd->nmcd.hdc, bgRgn, MyBrush);
    				DeleteObject(MyBrush);
    
    				SetTextColor(lplvcd->nmcd.hdc, RGB(255,255,255));
    
    				newFont = CreateFont(16, 0, 0, 0, FW_NORMAL, TRUE, FALSE, FALSE,
    										EASTEUROPE_CHARSET, 0, 0, CLEARTYPE_NATURAL_QUALITY,
    										DEFAULT_PITCH | FF_DONTCARE, L"Times New Roman");
    				oldFont = (HFONT)SelectObject(lplvcd->nmcd.hdc,newFont);
    
    				ListView_GetItemText(hListView,lplvcd->nmcd.dwItemSpec,0,iSubTxt1,64);
    				SetRect(&textRect, ItemRect.left+5,ItemRect.top, ItemRect.right, ItemRect.bottom);
    				DrawText(lplvcd->nmcd.hdc,iSubTxt1,-1,&textRect, DT_LEFT | DT_NOCLIP);
    				ListView_GetItemText(hListView,lplvcd->nmcd.dwItemSpec,1,iSubTxt2,64);
    				SetRect(&textRect, ItemRect.left+Width/3+5,ItemRect.top, ItemRect.right, ItemRect.bottom);
    				DrawText(lplvcd->nmcd.hdc,iSubTxt2,-1,&textRect, DT_LEFT | DT_NOCLIP);
    
    				SelectObject(lplvcd->nmcd.hdc,oldFont);
    				DeleteObject(newFont);
    
    				return CDRF_SKIPDEFAULT;
    			}
    

    Does having an audience for Your sins make You feel like You're special? Does it make You proud?
    • Marked As Answer byNorethel Friday, August 21, 2009 11:51 AM
    •  
  • Friday, August 21, 2009 4:07 PMTiKu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    You don't display any icons for the items, do you? I don't see any code that draws the icon.
    Windows 7 would be much better without DRM and Product Activation ;) (No, I'm no software pirate)
  • Saturday, August 22, 2009 10:00 AMNorethel Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Yes, I do :) Don't have to :)
    Does having an audience for Your sins make You feel like You're special? Does it make You proud?