Изменить границу ToolStripComboBox с помощью плоского стиля

Я хотел бы иметь возможность изменить цвет границы элементов управления ToolStripComboBox в некоторых моих панелях инструментов, поскольку цвет границы ComboBox по умолчанию при использовании с плоским стилем — SystemColors.Window, который в основном невидим по сравнению с цветом элемента управления по умолчанию панели инструментов. После долгих поисков в Reflector я не вижу очевидного способа сделать это, поскольку вся инфраструктура рендеринга ComboBox надежно защищена внутренними и частными интерфейсами.

За пределами ToolStrips обычное решение, которое я видел, для исправления цвета границы в ComboBox, которое я видел, заключается в подклассе ComboBox, переопределении WndProc и ручном окрашивании границы. Это не может работать для элементов управления ToolStripComboBox, поскольку внутренний элемент управления ComboBox является собственным частным подклассом ComboBox, и я не вижу способа заменить экземпляр элемента управления.

Альтернативное решение, которое я рассматриваю, — поместить один из расширенных объектов ComboBox в ToolStripControlHost, что позволит мне нарисовать границу, но тогда мне придется отказаться от некоторых профессиональных настроек рендерера. Вторичный недостаток, который я заметил, заключается в том, что я иногда мерцаю при наведении курсора.

Переключение моего дизайна на WPF не является приемлемым решением. Оборачивать элементы управления в родительские элементы управления для рисования границ также неприемлемо, так как это ничего не дает по сравнению с альтернативой ToolStripControlHost.

Есть ли у кого-нибудь умное решение для решения этой проблемы, или существует ли уже существующая (с разрешающей лицензией) повторная реализация стека рендеринга в плоском стиле ComboBox, которая устраняет некоторые недостатки в существующей реализации?


person Justin Aquadro    schedule 05.03.2012    source источник


Ответы (3)


Вот способ заставить это работать ... вроде :)

Создайте обработчик событий для Paint событие ToolStrip. Затем просмотрите все ToolStripComboBox и нарисуйте прямоугольник вокруг них.

    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);
        }
    }

Вот как это выглядит (обратите внимание, что вам может понадобиться отрегулировать высоту ToolStrip, чтобы предотвратить обрезание нарисованной границы):

введите здесь описание изображения

person gannaway    schedule 14.12.2013

улучшение: проверьте тип элемента панели инструментов, чтобы программа не падала, например, если это tooltipLabel.

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);
       }

}

person snir    schedule 07.05.2014
comment
Вы также можете просто использовать if (item is ToolStripComboBox cb) вместо as и != null - person Lakshya Goyal; 27.06.2019

toolStrip1.ComboBox.FlatStyle = FlatStyle.System;

Это устанавливает границу по умолчанию в стиле ОС вокруг поля со списком. В Windows 10 это светло-серая и тонкая рамка. Хотя, в зависимости от фона, это может не отображаться. В этом случае вы можете попробовать другие варианты, такие как FlatStyle.Popup.

Если пресеты не то, что вы ищете, другие ответы позволяют вам нарисовать собственную границу. Однако, поскольку прямоугольник рисуется с размером +1 пиксель вокруг поля со списком, граница на 1 пиксель больше, чем поле со списком. Удаление +1 и -1 тоже не работает.

person Lakshya Goyal    schedule 27.06.2019