0

I want to change the color of a selected item in a listbox to a specific ARGB value. When it's not selected it's showing the ForeColor I've defined in the Properties of my listBox.

But whatever I try it's either setting the brush to a predefined color (white, green, whatever), changing the color when selected & not selected for both in the same color... or it's not changing at all. The solutions I see on stackoverflow are XAML based, but I'm using Winforms C# .NET, so that's not an option.

I've managed to make a custom listBox already using OwnerDrawFixed as DrawMode and a custom DrawItem predefined like this:

        {
            SolidBrush myBrushBack = new SolidBrush(Color.FromArgb(255, 42, 42, 42));
            SolidBrush myBrushFore = new SolidBrush(Color.FromArgb(255, 62, 182, 86));

            if (e.Index < 0) return;
            e.DrawBackground();
            Graphics g = e.Graphics;
            Brush brush = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ?
                            myBrushBack : new SolidBrush(e.BackColor);
                            myBrushFore : new SolidBrush(e.ForeColor);

            g.FillRectangle(brush, e.Bounds);
            SizeF size = e.Graphics.MeasureString(listBoxTracks.ToString(), e.Font);
            e.Graphics.DrawString(listBoxTracks.Items[e.Index].ToString(), e.Font,
                     new SolidBrush(e.ForeColor), e.Bounds.Left + (e.Bounds.Width / 29 - size.Width / 39), e.Bounds.Top + (e.Bounds.Height / 2 - size.Height / 2), StringFormat.GenericDefault);
            e.DrawFocusRectangle();

        }

This code doesn't give me the right green I want + it changes the selected & not selected text color for both:

 e.Graphics.DrawString(listBoxTracks.Items[e.Index].ToString(), e.Font, Brushes.Green, e.Bounds, StringFormat.GenericDefault);

How it is behaving now: https://i.stack.imgur.com/rFUrP.jpg

How I want it to behave: https://i.stack.imgur.com/ZuePQ.jpg

Bas Curtiz
  • 73
  • 8
  • Se this one: [ListBox items do not show in OwnerDrawFixed Mode](https://stackoverflow.com/q/54831018/7444103). You can adapt it to show any color you want. Unless you actually want the terrible effect you have in your *How I want it to behave* sample. – Jimi May 21 '19 at 10:47
  • Thanks (once again) Jimi! Works like I wanna (without the terrible fx xD) – Bas Curtiz May 21 '19 at 11:31

1 Answers1

0

Thanks to Jimi, I've adapted the code and it works correctly now, using the code like this:

        {
            if (e.Index < 0) return;
            e.DrawBackground();
            bool isItemSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);
            using (SolidBrush bgBrush = new SolidBrush(isItemSelected ? Color.FromArgb(255, 42, 42, 42) : Color.FromArgb(255, 29, 29, 29)))
            using (SolidBrush itemBrush = isItemSelected ? new SolidBrush(Color.FromArgb(255, 62, 182, 86)) : new SolidBrush(Color.FromArgb(255, 176, 176, 176)))
            {
                string itemText = listBoxTracks.GetItemText(listBoxTracks.Items[e.Index]);
                e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
                SizeF size = e.Graphics.MeasureString(listBoxTracks.ToString(), e.Font);
                e.Graphics.FillRectangle(bgBrush, e.Bounds);
                e.Graphics.DrawString(itemText, e.Font, itemBrush, e.Bounds.Left + (e.Bounds.Width / 29 - size.Width / 39), e.Bounds.Top + (e.Bounds.Height / 2 - size.Height / 2), StringFormat.GenericDefault);
            }
            e.DrawFocusRectangle();
        }
Bas Curtiz
  • 73
  • 8
  • Remove those un-disposed/un-used brushes. If you want to alter the item's height, you have to do something quite different. The items cannot be changed once the control's handle is created without sending a `WM_MEASUREITEM` message. If you do it in any other way, the items' strings will begin to overlap in an *unpleasant* manner. – Jimi May 21 '19 at 11:40
  • @Jimi Removed the un-used brushes, thanks for pinpointing this out. I'm staring at https://stackoverflow.com/questions/1420674/c-sharp-measureitemevent-handler-e-itemheight-not-changing but not sure what suppose to happen. Can you show me how to properly set the height? I've used that code in order to make the text appear in the middle of the item. – Bas Curtiz May 21 '19 at 11:59
  • Subscribe to the `MeasureItem` event. This is raised when the control wants to know the height of the Item. You can set the `e.ItemHeight` to the desied measure. You can use the code you found in that link to *reset* the ListBox handle (when you change the `DrawMode`, the control is recreated, thus will also re-measure the Item height, which will be taken from what you specify with `e.ItemHeight`). – Jimi May 21 '19 at 12:42