locked
ComboBoxRenderer does not look like Windows 7 ComboBox RRS feed

  • Question

  • Hi,

    When I call Application.EnableVisualStyles in WinForms application on Windows 7, a ComboBox looks "modern" - it is a white background with a black arrow.  When I do not call EnableVisualStyles, the ComboBox is "legacy" - a gray background.

    However, ComboBoxRenderer.DrawDropDownButton always looks "legacy" - it always draws it with a gray background.  I also tried ControlPaint methods but it also looked "legacy."

    How do I draw custom combo box button that is "modern" in C# (or even p/Invoke to GDI or GDI+)?

    Thanks.

    Wednesday, March 5, 2014 5:33 PM

Answers

All replies

  • Hi tballard,

    Can you provide a simple sample about what you have done to set DrawDropDownButton?

    I recommend you check the property here http://msdn.microsoft.com/en-us/library/System.Windows.Forms.VisualStyles.VisualStyleElement.ComboBox.DropDownButton_properties(v=vs.110).aspx and check this blog to see about how you can custom combobox button:

    http://www.codeproject.com/Articles/18172/Appearance-Customizable-ComboBox

    Regards,



    Barry Wang
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Barry Wang Monday, March 17, 2014 2:38 AM
    Friday, March 7, 2014 6:48 AM
  • Hello,

    You know that you are asking this in the forum for the desktop user interface Windows Forms classes and api's.

    "Modern" is the official Microsoft name of the Microsoft Store Apps interface, therefore about what user interface are you talking? 

    Visit for "Modern" controls the forum of that interface.


    Success
    Cor

    Friday, March 7, 2014 10:45 AM
  • Hi Cor,

    Well, for this case op doesn't mean that modern control. He just mean a style with looks more fashionable. I've just build my Win 7 test machine and test what he mentioned. You can think his modern is like Win 7 Aero and his legacy is XP style.

    What he mentioned in my mind is just like change the style of a combobox dropdown button. However, in my test result,common style of ComboBoxRenderer.DrawDropDownButton is a white background with a black arrow. When you put your mouse on it, it will grey. This behavior is alright in my mind, to change it he can check the blog I showed.

    Regards,



    Barry Wang
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, March 11, 2014 6:53 AM
  • To the OP, Barry told me that you maybe with Modern does not mean the Microsoft meaning for it. 


    In the forum person try to help others. They do that on Information they get. Therefore try to give information instead of your opinion. Words like "modern" and "legacy" have for almost everybody another meaning.

    The word modern for instance starts with the discovery of America by the Europeans. I assume you does not mean that either, legacy is for many the use of programming in a punch card way, that is also not something you mean I guess.


    Success
    Cor

    Tuesday, March 11, 2014 10:16 AM
  • Too many, I appreciate your help for those moderation replies.


    Barry Wang
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, March 11, 2014 10:19 AM
  • I don't think this problem is actually solved.  I believe I am seeing the same problem as the OP.

    When I place an unaltered ComboBox on a form from the toolbox, the normal state of the dropdown button has no border and a white background.  The only thing shown is a down arrow.  In Windows 7 it's a black triangle pointing down, and in Windows 8 it's a V.

    When I draw the combobox dropdownbutton using a VisualStyleRenderer or a ComboBoxRenderer I don't get that white background with any of the four possible states: Disabled, Normal, Hot, or Pressed.  I expect Normal to be the one I'm after, but it's got a grey background and a border.  Hot and Pressed do look as I'd expect.  Disabled doesn't look like when a combobox.Enabled = false either, but I'm not really after that one.

    It seems like a problem to me.  Can you show me how to get that same white background but still have the correct triangle or V depending on the OS?  I'd hate to think I should draw it myself based on the OS/theme?

    You can use the code example in the link provided by Barry to experience the problem.
    http://msdn.microsoft.com/en-us/library/System.Windows.Forms.VisualStyles.VisualStyleElement.ComboBox.DropDownButton_properties(v=vs.110).aspx

    Drag a plain combobox from the toolbox onto your form to compare.
    Thank you for any help.
    Buzz


    Wednesday, January 14, 2015 3:30 AM
  • By looking at Microsoft's Reference Source, I can see the problem.
    The ComboBoxRender DrawDropDownButton() method does not allow you to choose which part to draw and is hard-coded to use part number ComboBoxElement.Part. ComboBoxElement is defined to be VisualStyleElement.ComboBox.DropDownButton.  In order to draw the style of button that the OP and I want, you have to use VisualStyleElement.ComboBox.DropDownRightButton.

    Another annoyance is that DropDownRightButton is internal, so that's too bad.

    To solve this problem I created an enum to represent each part number of the combobox, and then copied the reference code and created my own ComboBoxRendererEx that modifies the DrawDropDownButton(...) method to allow a part to be specified, like this:

    /// <summary>
    /// ComboBox parts as defined at
    /// http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/VisualStyles/VisualStyleElement.cs,5009862ba4454b7e
    /// </summary>
    public enum ComboBoxElementParts
    {
        DropDownButton = 1,
        Border = 4,
        ReadOnlyButton = 5,
        DropDownButtonRight = 6,
        DropDownButtonLeft = 7
    }
    
    ---------------------------
    
    public static void DrawDropDownButton(Graphics g, Rectangle bounds, ComboBoxState state, ComboBoxElementParts part = ComboBoxElementParts.DropDownButton)
    {
        if (visualStyleRenderer == null)
        {
            visualStyleRenderer = new VisualStyleRenderer(ComboBoxElement.ClassName, (int)part, (int)state);
        }
        else
        {
            visualStyleRenderer.SetParameters(ComboBoxElement.ClassName, (int)part, (int)state);
        }
    
        visualStyleRenderer.DrawBackground(g, bounds);
    }

    Now I can draw a custom combobox and get the look of a default combobox using something like:
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
    
        // Draw control border
        ComboBoxRendererEx.DrawDropDownButton(e.Graphics, this.ClientRectangle, this.textBoxState, ComboBoxElementParts.Border);
    
        // Draw drop down button
        ComboBoxRendererEx.DrawDropDownButton(e.Graphics, this.dropDownArrowRectangle, this.dropDownArrowState, ComboBoxElementParts.DropDownButtonRight);
    }
    

    • Proposed as answer by buzzweetman Friday, January 23, 2015 1:31 PM
    Friday, January 23, 2015 1:30 PM
  • There are 3 DropDownStyles for combobox and each one renders differently.

    Below are 3 simple methods to draw a combobox dependant on style and state:

            private void DrawSimpleCombo(Graphics graphics, Rectangle bounds, ComboBoxState state)
            {
                VisualStyleRenderer renderer;
    
                if (state != ComboBoxState.Disabled)
                {
                    renderer = new VisualStyleRenderer("COMBOBOX", 4, 2);
                    renderer.DrawBackground(graphics, bounds);
               }
                else
                {
                    renderer = new VisualStyleRenderer("EDIT", 1, 1);
                    renderer.DrawBackground(graphics, bounds);
    
                    Rectangle rc = renderer.GetBackgroundContentRectangle(graphics, bounds);
                    rc.Inflate(-2, -2);
                    graphics.FillRectangle(SystemBrushes.Control, rc);
                }
                
            }
    
            private void DrawDropDownCombo(Graphics graphics, Rectangle bounds, ComboBoxState state, bool focused)
            {
                VisualStyleRenderer renderer = new VisualStyleRenderer("COMBOBOX", 4, state > ComboBoxState.Normal || focused ? 2 : 1);
    
                VisualStyleRenderer buttonRenderer = new VisualStyleRenderer("COMBOBOX", 7, (int)state);
    
                Size szP = buttonRenderer.GetPartSize(graphics, ThemeSizeType.True);
    
                buttonRenderer.SetParameters("COMBOBOX", 7, (int)state);
                Size szR = buttonRenderer.GetPartSize(graphics, ThemeSizeType.True);
    
                buttonRenderer.SetParameters("COMBOBOX", 6, (int)state);
                Size szL = buttonRenderer.GetPartSize(graphics, ThemeSizeType.True);
    
                Size sz = new Size(szL.Width + szR.Width + szP.Width, szP.Height);
    
                if (state != ComboBoxState.Disabled)
                {                
                    renderer.DrawBackground(graphics, bounds);
                }
                else
                {
                    renderer = new VisualStyleRenderer("EDIT", 1, 1);
                    renderer.DrawBackground(graphics, bounds);
    
                    Rectangle client = renderer.GetBackgroundContentRectangle(graphics, bounds);
                    client.Inflate(-2, -2);
                    client.Width -= sz.Width;
    
                    graphics.FillRectangle(SystemBrushes.Control, client);
                }
    
    
                Rectangle rc = Rectangle.FromLTRB(bounds.Right - (sz.Width), bounds.Top, bounds.Right, bounds.Bottom);
    
                buttonRenderer.DrawBackground(graphics, rc);
            }
    
            private void DrawDropDownListCombo(Graphics graphics, Rectangle bounds, ComboBoxState state)
            {
                VisualStyleRenderer renderer = new VisualStyleRenderer("COMBOBOX", 5, (int)state);
                renderer.DrawBackground(graphics, bounds);
    
                renderer.SetParameters("COMBOBOX", 1, 1);
                Size szP = renderer.GetPartSize(graphics, ThemeSizeType.True);
    
                renderer.SetParameters("COMBOBOX", 7, 1);
                Size szR = renderer.GetPartSize(graphics, ThemeSizeType.True);
    
                renderer.SetParameters("COMBOBOX", 6, state == ComboBoxState.Disabled ? 4 : 1);
                Size szL = renderer.GetPartSize(graphics, ThemeSizeType.True);
    
                Size sz = new Size(szL.Width + szR.Width + szP.Width, szP.Height);
    
                Rectangle rc = Rectangle.FromLTRB(bounds.Right - (sz.Width), bounds.Top, bounds.Right, bounds.Bottom);
    
                renderer.DrawBackground(graphics, rc);
            }
    
            public enum ComboBoxState
            {
                Normal = 1, Hot, Pressed, Disabled
            }


    Mick Doherty
    http://dotnetrix.co.uk
    http://glassui.codeplex.com


    • Edited by Mick Doherty Saturday, January 24, 2015 12:43 PM
    Saturday, January 24, 2015 12:26 PM