Обзор
В настоящее время я работаю над системой тем для своего приложения, позволяющей пользователям выбирать темные светлые и темные (аналогично Visual Studio).Пока весь процесс довольно прост;однако есть несколько вещей, с которыми у меня все еще есть пара проблем (ну, больше желания узнать, есть ли лучшие способы сделать это).В процессе разработки я провел немало исследований по изменению цвета выделения элементов управления, которые его поддерживают (ListView
, ComboBox
, ListBox
, TextBox
, RichTextBox
и т. Д.).Я обнаружил, что наиболее простой способ сделать это (особенно с помощью элементов управления стилями списка) - выполнить пользовательское рисование элементов, используя события, доступные для каждого элемента управления.Я знаю, что RichTextBox
имеет свойство SelectionBackColor
, которое позволит вам изменить его цвет выделения , однако элемент управления TextBox
не предлагает ни того же свойства, ни чего-либо подобного, которое я нашел.
С помощью элемента управления ListBox
он не содержит какого-либо свойства выбора цвета для дальнейшей настройки, что означает, что мне нужно использовать события OwnerDraw
и DrawItem
/ DrawSubItem
для пользовательской отрисовки заднего цветапри установке свойства HideSelection
на false
, чтобы помочь с изменением при потере фокуса.
Элементы управления ComboBox
и ListBox
достаточно просты для изменения с помощьюСобытие DrawItem
и его настройку на OwnerDraw
, например, элемент управления ListBox
.
Как мы все знаем, существует множество различных элементов управления, которые поддерживают выбор пользователя, и я мог бы продолжать и продолжать свои исследования,но я думаю, что того, что я предоставил, достаточно, чтобы помочь описать, почему я здесь.
Вопрос
Поскольку код манипулирует всемиэто через одинКласс серьезно утомителен и ограничивает будущие разработчики (особенно если они выполняют пользовательское рисование элементов в этих элементах управления).Мне интересно, есть ли упрощенный способ манипулирования только цветом выделения.Я уже нашел здесь пост в StackOverflow, который использует DllImport
для манипулирования цветом подсветки системы;однако, изменение вещей на уровне ОС не кажется ни умным, ни безопасным делом для чего-то такого простого.Я так же неохотно манипулирую системным кодом, как и слепо манипулирую регистрами ядра в сборке MIPS.
Использованный мной пост в StackOverflow:
[DllImport("user32.dll")]
static extern bool SetSysColors(int cElements, int[] lpaElements, uint[] lpaRgbValues);
void ChangeSelectColour(Color color) {
const int COLOR_HIGHLIGHT = 13;
const int COLOR_HIGHLIGHTTEXT = 14;
// You will have to set the HighlightText colour if you want to change that as well.
//array of elements to change
int[] elements = { COLOR_HIGHLIGHT };
List<uint> colours = new List<uint>();
colours.Add((uint)ColorTranslator.ToWin32(color));
//set the desktop color using p/invoke
SetSysColors(elements.Length, elements, colours.ToArray());
}
Это единственный способделая это?Если это так, я могу отказаться от идеи изменить цвет выделения во всем приложении, поскольку это не кажется слишком безопасным (если кто-то не может доказать обратное).
Моя текущая реализация (трудный путь, упомянутый в разделе обзора) выглядит следующим образом (только небольшой пример):
public static void ApplyStyles(Control c) {
if (c is Button) {
Button b = (Button)c;
b.FlatStyle = FlatStyle.Flat;
b.FlatAppearance.BorderSize = 0;
}
if (c is RoundedPanel || c is PictureBox) {
// Do nothing.
} else {
if (c is Label) {
if (c.Parent is RoundedPanel) {
// Do nothing.
} else {
c.BackColor = BackColor;
c.ForeColor = ForeColor;
}
} else {
c.BackColor = BackColor;
c.ForeColor = ForeColor;
}
if (c is ListView) {
ListView lv = (ListView)c;
// PSEUDO BEGIN
lv.OwnerDraw = true;
lv.DrawItem += DrawListViewItem;
lv.DrawSubItem += DrawListViewSubItem;
// PSEUDO END
if (Style = Themes.Dark)
lv.GridLines = false;
foreach (ListViewItem lvi in lv.Items) {
lvi.BackColor = BackColor;
lvi.ForeColor = ForeColor;
}
}
}
}
Теперь, если бы вы могли представить, что нужно делать это для каждого типа, поддерживающего выбор пользователя, вы получите несколько условий для универсального типа, которые затем создадутнастраиваемые события для рисования элементов, содержащихся в элементе управления, которые могут стать еще более сложными, когда вы начнете изучать поддержку изображений, флажки и т. д.Этот код может расширяться во все стороны довольно быстро, если нет каких-либо общих методов для изменения цвета выделения, и в моем случае это не стоило бы усилий (если бы я не сделал его с очень низким приоритетом и иногда работал над ним).через годы).
Кроме того, имейте в виду, когда вы делаете предложения;Я работаю в правительственной среде, поэтому все сторонние продукты должны быть одобрены, и в моем случае 100% веская причина того, почему нам нужен этот продукт, должна быть предоставлена для утверждения, чтобы сторонние тематические продукты не помоглив моем случае.
Я благодарю вас всех за то, что вы нашли время прочитать это, и если у кого-то есть какие-либо идеи, пожалуйста, дайте мне знать!
ПРИМЕЧАНИЕ
Если вы чувствуете, что я пропустил какую-либо необходимую информацию, или если я хочу прояснить некоторые вещи, не стесняйтесь комментировать и дайте мне знать, чтобы я мог обновить ясность поста для будущих читателей.
Ссылки
RichTextBox.SelectionBackColor
Использование SelectionBackColor
, чтобы получить или установить цвет выделенного текста в RichTextBox
.Если текст в настоящее время не выбран, свойство SelectionBackColor
применяется к текущей позиции каретки.Символы, которые вводятся с этой позиции, имеют указанное SelectionBackColor
.
ComboBox.DrawItem
Это событиеиспользуется владельцем, нарисованным ComboBox
.Это событие можно использовать для выполнения задач, необходимых для рисования элементов в ComboBox
.
ListBox.DrawItem
Это событие используется нарисованным владельцем ListBox.Событие возникает только в том случае, если для свойства DrawMode установлено значение DrawMode.OwnerDrawFixed или DrawMode.OwnerDrawVariable.Это событие можно использовать для выполнения задач, необходимых для рисования элементов в ListBox.
Дополнительные ссылки
Событие ComboBox.DrawItem
Событие ListBox.DrawItem