简体   繁体   中英

Change Border of ToolStripComboBox with Flat Style

I would like to be able to change the border color of ToolStripComboBox controls in some of my toolstrips, since the default border color of ComboBoxes when used with flat styling is SystemColors.Window, which is basically invisible against the default control color of the toolstrip. After a lot of digging around in Reflector, I don't see any obvious way to do this, since all the infrastructure behind ComboBox rendering is highly protected behind internal and private interfaces.

Outside of ToolStrips, a common solution I've seen proposed for fixing border color on ComboBoxes is to subclass ComboBox, override WndProc, and manually paint the border. This can't work for ToolStripComboBox controls since the internal ComboBox control is its own private subclass of ComboBox, with no way that I can see to replace the instance of the control.

An alternative solution I'm considering is putting one of the extended ComboBox objects into a ToolStripControlHost, which allows me to draw a border, but then I have to give up some of the professional renderer tweaks. A secondary drawback I've noticed is that I get occasional flicker during mouseover.

Switching my design to WPF is not an acceptable solution. Wrapping controls in parent controls for drawing borders is also not acceptable, as this gains nothing over the ToolStripControlHost alternative.

Does anyone have a clever solution to defeat this problem, or is there an existing (permissively-licensed) re-implementation of the ComboBox flat-style rendering stack out in the wild, which fixes some of the shortcomings in the existing implementation?

Here's a way to make it work ... sort of :)

Create an event handler for the Paint event of the ToolStrip . Then loop through all of the ToolStripComboBoxes and paint a rectangle around them.

    private Color cbBorderColor = Color.Gray;
    private Pen cbBorderPen = new Pen(SystemColors.Window);

    private void toolStrip1_Paint(object sender, PaintEventArgs e)
    {            
        foreach (ToolStripComboBox cb in toolStrip1.Items)
        {
            Rectangle r = new Rectangle(
                cb.ComboBox.Location.X - 1,
                cb.ComboBox.Location.Y - 1,
                cb.ComboBox.Size.Width + 1,
                cb.ComboBox.Size.Height + 1);

            cbBorderPen.Color = cbBorderColor;
            e.Graphics.DrawRectangle(cbBorderPen, r);
        }
    }

Here's what it looks like (note that you may need to adjust the Height of the ToolStrip to prevent the painted border from being cut off):

在此处输入图片说明

improvement : check the type of the toolstrip item, so the program will not crush if it is toolstipLabel for example.

foreach (var item in toolStrip1.Items)
{
      var asComboBox = item as ToolStripComboBox;
      if (asComboBox != null)
      {
          var location = asComboBox.ComboBox.Location;
          var size = asComboBox.ComboBox.Size;
          Pen cbBorderPen = new Pen(Color.Gray);
          Rectangle rect = new Rectangle(
                  location.X - 1,
                  location.Y - 1,
                  size.Width + 1,
                  size.Height + 1);

          e.Graphics.DrawRectangle(cbBorderPen, rect);
       }

}

toolStrip1.ComboBox.FlatStyle = FlatStyle.System;

This sets the default, OS-styled, border around the combo box. It is a light grey and thin border on Windows 10. Although, depending on the background, this may not show. In which case, you could try the other options like FlatStyle.Popup .

If the presets aren't what you are looking for, the other answers allow you to draw a custom border. However, since the rectangle is drawn with +1 pixel size around the combo box, the border is 1 pixel larger than the combo box. Removing the +1s and -1s doesn't work either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM