Универсальный выбор изменения цвета WinForms Controls - PullRequest
0 голосов
/ 05 июня 2018

Обзор

В настоящее время я работаю над системой тем для своего приложения, позволяющей пользователям выбирать темные светлые и темные (аналогично 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...