Гид по технологиям

Добавление тем в Windows Forms: Light, Nature и Dark

8 min read Разработка Обновлено 05 Dec 2025
Темы в Windows Forms: Light, Nature, Dark
Темы в Windows Forms: Light, Nature, Dark

Код на компьютере рядом с растениями

В современных десктопных приложениях часто нужна возможность менять тему интерфейса. Это улучшает удобство для пользователей и позволяет учитывать условия освещения и предпочтения. В Windows Forms можно реализовать темы, создавая управляемые наборы цветов и переключая их по нажатию кнопки.

В этой статье вы получите:

  • пошаговое руководство по созданию проекта и элементов управления;
  • готовые примеры кода для переключения тем;
  • рекомендации по хранению и восстановлению выбранной темы;
  • чек-листы для разработчиков, дизайнеров и тестировщиков;
  • сравнительный список альтернатив и советы по совместимости.

Что вам нужно заранее

  • Visual Studio (любой поддерживаемой версии для WinForms).
  • Базовые знания C# и работы с дизайнером форм.
  • Проект Windows Forms (Framework или .NET Core/5/6/7 — см. раздел совместимости).

Шаг 1. Создайте проект и расположите базовые элементы управления

  1. Создайте новый проект Windows Forms в Visual Studio.
  2. Добавьте на форму три больших кнопки (button1, button2, button3) и одну метку (label1).
  3. Отрегулируйте размеры и стиль через окно свойств.

В примере мы использовали следующие настройки через окно свойств:

КонтролСвойствоЗначение
button1Size580, 200
button1FlatStyleFlat
button1TextUsers
button2Size580, 100
button2FlatStyleFlat
button2TextAccounts
button3Size580, 100
button3FlatStyleFlat
button3TextPermissions
label1TextCopyright 2022

Поиск кнопки в панели инструментов

Кнопки на форме в WinForms

Метка на форме под кнопками

Окно свойств для кнопки в WinForms

Шаг 2. Добавьте кнопку настроек тем и список тем

Создайте дополнительную кнопку, которая будет показывать/скрывать выбор темы, и три кнопки для самих тем (Light, Nature, Dark).

  1. Добавьте кнопку настроек и задайте свойства:
СвойствоЗначение
NamebtnThemeSettings
FlatStyleFlat
Size200, 120
TextThemes

Окно свойств для кнопки в WinForms

  1. Добавьте три кнопки для тем и установите им начальные цвета и видимость в False:
КонтролСвойствоЗначение
btnLightThemeBackColorWhiteSmoke
btnLightThemeSize200, 80
btnLightThemeFlatStyleFlat
btnLightThemeTextLight
btnLightThemeVisibleFalse
btnNatureThemeBackColorDarkSeaGreen
btnNatureThemeSize200, 80
btnNatureThemeFlatStyleFlat
btnNatureThemeTextNature
btnNatureThemeVisibleFalse
btnDarkThemeBackColorDimGray
btnDarkThemeForeColorWhite
btnDarkThemeSize200, 80
btnDarkThemeFlatStyleFlat
btnDarkThemeTextDark
btnDarkThemeVisibleFalse

Окно свойств для кнопки в WinForms

  1. Создайте обработчик клика для кнопки настроек тем и переключайте видимость трех кнопок тем:
private void btnThemeSettings_Click(object sender, EventArgs e)
{
    btnNatureTheme.Visible = !btnNatureTheme.Visible;
    btnLightTheme.Visible = !btnLightTheme.Visible;
    btnDarkTheme.Visible = !btnDarkTheme.Visible;
}

Запустите приложение и убедитесь, что по умолчанию кнопки тем скрыты, а по нажатию на Themes они появляются и исчезают.

Play button in Visual Studio window

App at runtime with themes settings button

WinForms app at runtime showing available themes

Шаг 3. Управление наборами цветов (темами)

Лучше хранить цвета темы в одном месте — для этого подойдёт словарь Dictionary. Так вы сможете многократно применять наборы и централизованно обновлять палитру.

  1. Внутри класса Form объявите перечисление и словари:
enum ThemeColor
{
    Primary,
    Secondary,
    Tertiary,
    Text
}

Dictionary Light = new Dictionary();
Dictionary Nature = new Dictionary();
Dictionary Dark = new Dictionary();
  1. В конструкторе формы инициализируйте словари:
public Form1()
{
    InitializeComponent();

    // Add dictionaries here
    Light = new Dictionary() {
        { ThemeColor.Primary, Color.WhiteSmoke },
        { ThemeColor.Secondary, Color.Silver },
        { ThemeColor.Tertiary, Color.White },
        { ThemeColor.Text, Color.Black }
    };
    Nature = new Dictionary() {
        { ThemeColor.Primary, Color.DarkSeaGreen },
        { ThemeColor.Secondary, Color.AliceBlue },
        { ThemeColor.Tertiary, Color.Honeydew },
        { ThemeColor.Text, Color.Black }
    };
    Dark = new Dictionary() {
        { ThemeColor.Primary, Color.DimGray },
        { ThemeColor.Secondary, Color.DimGray },
        { ThemeColor.Tertiary, Color.Black },
        { ThemeColor.Text, Color.White }
    };

    // Apply default theme
    ChangeTheme(Light[ThemeColor.Primary], Light[ThemeColor.Secondary], Light[ThemeColor.Tertiary]);
    ChangeTextColor(Light[ThemeColor.Text]);
}

WinForms app at runtime with default theme applied

Шаг 4. Функции смены темы и цвета текста

Создайте функции, которые применяют цвета к элементам интерфейса. Это упрощает повторное использование и тестирование.

private void ChangeTheme(Color primaryColor, Color secondaryColor, Color tertiaryColor)
{
    // Change background color of buttons
    btnThemeSettings.BackColor = primaryColor;
    button1.BackColor = primaryColor;
    button2.BackColor = secondaryColor;
    button3.BackColor = secondaryColor;
    this.BackColor = tertiaryColor;
}

private void ChangeTextColor(Color textColor)
{
    // Change color of text
    button1.ForeColor = textColor;
    button2.ForeColor = textColor;
    button3.ForeColor = textColor;
    label1.ForeColor = textColor;
    btnThemeSettings.ForeColor = textColor;
}

И в обработчиках нажатия на кнопки тем используйте словари:

private void btnLightTheme_Click(object sender, EventArgs e)
{
    ChangeTheme(Light[ThemeColor.Primary], Light[ThemeColor.Secondary], Light[ThemeColor.Tertiary]);
    ChangeTextColor(Light[ThemeColor.Text]);
}

private void btnNatureTheme_Click(object sender, EventArgs e)
{
    ChangeTheme(Nature[ThemeColor.Primary], Nature[ThemeColor.Secondary], Nature[ThemeColor.Tertiary]);
    ChangeTextColor(Nature[ThemeColor.Text]);
}

private void btnDarkTheme_Click(object sender, EventArgs e)
{
    ChangeTheme(Dark[ThemeColor.Primary], Dark[ThemeColor.Secondary], Dark[ThemeColor.Tertiary]);
    ChangeTextColor(Dark[ThemeColor.Text]);
}

WinForms app at runtime showing Nature theme

WinForms app at runtime showing dark theme

Сохранение выбранной темы между запусками

Рекомендуемые варианты для хранения пользовательских настроек:

  • Properties.Settings (Application Settings) — простая кросс-платформенная опция внутри .NET;
  • JSON-файл в %AppData% (Environment.SpecialFolder.ApplicationData) — удобно версионировать и редактировать вручную;
  • реестр Windows — использовать осторожно; подходит для специфичных корпоративных сценариев.

Пример сохранения через Properties.Settings:

// В Settings.settings добавьте ключ CurrentTheme типа string
private void SaveTheme(string themeName)
{
    Properties.Settings.Default.CurrentTheme = themeName;
    Properties.Settings.Default.Save();
}

private void LoadTheme()
{
    var name = Properties.Settings.Default.CurrentTheme;
    if (name == "Nature") btnNatureTheme.PerformClick();
    else if (name == "Dark") btnDarkTheme.PerformClick();
    else btnLightTheme.PerformClick();
}

Вызовите LoadTheme() в конструкторе после InitializeComponent() и инициализации словарей.

Важно: не сохраняйте в настройках данные, требующие защиты (пароли, токены). Для них используйте безопасное хранилище.

Доступность и читаемость

  • Проверяйте контраст текста и фона (WCAG подходы). Для базовой проверки используйте соотношение контраста 4.5:1 для нормального текста.
  • Для тёмных тем используйте не чистый чёрный текст на ярких фонах — лучше слегка смещённые оттенки.
  • Обеспечьте переключение с клавиатуры (Tab/Enter) и доступность для экранных читалок (AccessibleName, AccessibleDescription).

Совет: делайте тестовые сценарии с реальными пользователями и автоматическими проверками контраста.

Альтернативные подходы и расширяемость

  1. Темы как набор ресурсов (ResourceDictionary): хранить цвета и стили в ресурсах и менять их программно.
  2. Создание классической темы через интерфейс ITheme с методами ApplyTo(Form form) — удобно для расширяемости и unit-тестов.
  3. Использование библиотек UI-стилей и фреймворков (например, MetroFramework, MaterialSkin) для более богатых тем и готовых компонентов.

Когда этот подход может не подойти:

  • если в приложении много кастомных отрисованных контролов, их придётся адаптировать вручную;
  • если нужна динамическая смена стилей для каждой части приложения отдельно — лучше внедрить централизованный менеджер тем.

Совместимость и миграция

Таблица совместимости по платформам .NET:

ПлатформаПримечания

| .NET Framework (4.6–4.8) | Полная поддержка WinForms; код из статьи работает без изменений. | .NET Core 3.1 | Поддержка WinForms доступна; возможны отличия в визуальном оформлении в зависимости от среды. | .NET 5/6/7 | Поддержка WinForms; рекомендуется тестировать поведение цветов и DPI.

При миграции из .NET Framework в .NET Core/.NET 5+ проверьте:

  • корректность ссылок на System.Drawing и Color;
  • поведение DPI и масштабирования;
  • дескрипторы конфигурации Properties.Settings (иногда надо мигрировать вручную).

Чек-листы по ролям

Разработчик:

  • создать словари тем и функции применения цветов;
  • обработать сохранение/загрузку выбранной темы;
  • обеспечить переключение с клавиатуры;
  • покрыть код простыми unit-тестами (при наличии абстракции ITheme).

Дизайнер:

  • подготовить наборы цветов с учётом контраста;
  • удостовериться, что иконки/изображения выглядят в каждой теме;
  • предоставить переменные для состояний hover/active/disabled.

QA:

  • проверить все темы на разных разрешениях и масштабах DPI;
  • проверить доступность клавиатурой и через скринридеры;
  • тестировать сохранение темы между запусками.

Тесты и критерии приёмки

Критерии приёмки:

  • по умолчанию приложение открывается в Light теме;
  • при выборе темы цвета всех основных элементов изменяются корректно;
  • выбранная тема сохраняется и восстанавливается при следующем запуске;
  • контраст текста не падает ниже приемлемого уровня для основных элементов.

Минимальные тестовые случаи:

  1. Запуск приложения — проверка Light по умолчанию.
  2. Нажатие Themes — кнопки тем отображаются.
  3. Выбор Nature — все цвета соответствуют словарю Nature.
  4. Выбор Dark — проверка белого текста на тёмном фоне.
  5. Перезапуск приложения — тема сохраняется.

Ментальные модели и эвристики при выборе цветов

  • Слойность: разделяйте Primary (главные элементы), Secondary (контекстные элементы), Tertiary (фон) и Text (типографика).
  • Контраст: текст должен быть читаемым на любом фоне; используйте инструменты для расчёта контраста.
  • Универсальность: выбирайте цвета, которые не ломают фирменную палитру при применении к иконкам и фотографиям.

Быстрый план внедрения (SOP)

  1. Спроектировать словари тем и перечисление ThemeColor.
  2. Добавить UI-кнопки для переключения и скрыть их по умолчанию.
  3. Реализовать ChangeTheme и ChangeTextColor.
  4. Добавить сохранение выбранной темы (Settings/JSON).
  5. Провести тесты на разных масштабах и с клавиатурой.
  6. Подготовить дизайн-проверку контраста.

Пример расширения: интерфейс ITheme и менеджер тем

Идея: абстрагировать тему через интерфейс, чтобы упростить тестирование и добавление новых тем.

public interface ITheme
{
    string Name { get; }
    Dictionary Palette { get; }
    void ApplyTo(Form form);
}

Менеджер тем может хранить список ITheme и обеспечивать уведомление о смене темы через событие.

Decision flowchart (Mermaid)

flowchart TD
    A[Нужна тема в приложении?] --> B{Требования}
    B -->|Простая| C[Использовать словари Color]
    B -->|Расширяемая| D[Реализовать ITheme и ThemeManager]
    B -->|Много кастомных контролов| E[Рефакторинг контролов и ручная адаптация]
    C --> F[Сохранение через Settings или JSON]
    D --> F
    E --> F

(Flowchart показывает простой выбор архитектуры для темы: словари для простых случаев, интерфейс для масштабируемых решений.)

Шаблон словаря тем (чек-лист для дизайнеров)

ПолеОписание
PrimaryЦвет главных кнопок/панелей
SecondaryЦвет вторичных кнопок/карточек
TertiaryФон формы
TextЦвет основного текста

Используйте этот шаблон для каждой темы и сохраняйте в одном месте (файл JSON, ресурс или класс).

Блок примечаний и ограничений

Important: Если ваше приложение содержит сторонние или кастомные контролы, убедитесь, что они поддерживают изменение BackColor и ForeColor. Не все сторонние компоненты корректно реагируют на программную смену цветов.

Note: В этой инструкции использованы встроенные цвета Visual Studio (Color.*). При желании замените их на свои HEX-значения через ColorTranslator.FromHtml(“#rrggbb”).

Краткое резюме

  • Реализуйте темы через перечисление ThemeColor и Dictionary для каждой темы.
  • Создайте функции ChangeTheme и ChangeTextColor для централизованного применения цветов.
  • Сохраняйте выбор пользователя через Settings или JSON, и обеспечьте доступность и адекватный контраст.
  • Для масштабируемости используйте интерфейсы и менеджеры тем.

1-line glossary:

  • ThemeColor — перечисление слоёв цвета: Primary, Secondary, Tertiary, Text.

Если нужно, я могу подготовить ZIP с примером проекта, JSON-шаблонами тем и unit-тестами для менеджера тем.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Сброс настроек поиска Windows до стандартных
Windows

Сброс настроек поиска Windows до стандартных

Как посмотреть старые снимки Street View
Карты

Как посмотреть старые снимки Street View

Воспроизведение и исследование звука в JES
Руководство

Воспроизведение и исследование звука в JES

Как сохранить веб‑страницу для офлайн‑чтения
Мобильные устройства

Как сохранить веб‑страницу для офлайн‑чтения

Отключить кнопку «Параметры вставки» в Excel
Excel

Отключить кнопку «Параметры вставки» в Excel

Пакетное переименование файлов — Python
Программирование

Пакетное переименование файлов — Python