Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change ComboBox border outline color

I am trying to manage the color of the ComboBox. While it is possible to change the background color, I cannot find a property for the border outline.

Just drawing a square as border wont do in a dark theme because of the arrow. This leads me to the conclusion that this border might be an actual image file.

Is it possible to replace this?

enter image description here

UPDATE: I have implemented the Solution of @AhmedAbdelhameed - It looks a lot better now. However for the flat style, I had to adjust the rectangle like the following:

using (var p = new Pen(this.BorderColor, 1))
{
    g.DrawRectangle(p, 0, 0, Width - buttonWidth - 1, Height - 1);
}

I also exchanged the 'BorderColor' to match the rest of my UI:

public CustomComboBox()
{
    BorderColor = Color.Gray;
} 

This is the result so far: enter image description here enter image description here

What I would like to be able to do now is to change the actual drop down button (maybe with an overlay png) only in dark theme

UPDATE: I have been able to add a pricturebox to the custom Control with the following code:

using (var g = Graphics.FromHwnd(Handle))
{
    using (var p = new Pen(this.BorderColor, 1))
    {
        g.DrawRectangle(p, 0, 0, Width - buttonWidth - 1, Height - 1);
    }
    if (Properties.Settings.Default.Theme == "Dark")
    {
        g.DrawImageUnscaled(Properties.Resources.dropdown, new Point(Width - buttonWidth - 1));
    }
}

it looks awesome! more or less by coincidence which I do not understand, the dark dropdown button even disappears, when I change the theme in the theme combobox.

Before - After Comparisation: enter image description here enter image description here

like image 986
julian bechtold Avatar asked Sep 27 '18 16:09

julian bechtold


1 Answers

With the help of this answer, I was able to come up with the following:

First, add the following into your form to avoid flickering:

protected override CreateParams CreateParams
{
    get
    {
        CreateParams handleParam = base.CreateParams;
        handleParam.ExStyle |= 0x02000000;      // WS_EX_COMPOSITED
        return handleParam;
    }
}

Now, add the following class to your project:

public class CustomComboBox : ComboBox
{
    private const int WM_PAINT = 0xF;
    private int buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_PAINT)
        {
            using (var g = Graphics.FromHwnd(Handle))
            {
                // Uncomment this if you don't want the "highlight border".
                /*
                using (var p = new Pen(this.BorderColor, 1))
                {
                    g.DrawRectangle(p, 0, 0, Width - 1, Height - 1);
                }*/
                using (var p = new Pen(this.BorderColor, 2))
                {
                    g.DrawRectangle(p, 2, 2, Width - buttonWidth - 4, Height - 4);
                }
            }
        }
    }

    public CustomComboBox()
    {
        BorderColor = Color.DimGray;
    }

    [Browsable(true)]
    [Category("Appearance")]
    [DefaultValue(typeof(Color), "DimGray")]
    public Color BorderColor { get; set; }
}

Rebuild the project, replace the ComboBox controls with the new CustomComboBox, set the BorderColor property to a color of your choice, and you're good to go.

Result:

ComboBox_BorderColor

Update:

Using the following values seems to give a better result (specially when clicking the dropdown button), but you'll still probably need to draw the first rectangle (the one commented above) to avoid showing the "highlight border" around the button only:

using (var p = new Pen(this.BorderColor, 3))
{
    g.DrawRectangle(p, 1, 1, Width - buttonWidth - 3, Height - 3);
}
like image 78
41686d6564 stands w. Palestine Avatar answered Sep 28 '22 00:09

41686d6564 stands w. Palestine