notes's People
Forkers
abhishekkapsnotes's Issues
.NET WinForms easy color scheme
Как-то ночью я писал код. Мониторы ярко светили, и, чтобы уменьшить яркость, я включил тёмную тему IDE. Стало лучше, но оставался второй монитор с открытым проводником Windows, поэтому пришлось включить тёмную тему Windows. Стало нормально, до того момента, как я не запустил WinForms программу, над которой в этот момент работал.
Какой она была до этого:
Что предстало моим глазам:
Так жизнь показала мне, почему не следует хардкодить цвета. Вместо этого нужно везде использовать...
Системные цвета
SystemColors.ControlText
, а также системные кисти SystemBrushes.ActiveCaption
, и карандаши.
Производные цвета
Как вы думаете, какой системный цвет соответствует розовой подсветке синтаксической ошибки на скрине выше? Никакой, в этом легко убедиться, взглянув в таблицу системных цветов Windows, источник stackoverflow. Розовых, оранжевых и зелёных цветов нет.
Чтобы в этих условиях избегать хардкода таких цветов, как розовый, придётся в буквальном смысле слова выкручиваться.
Иконки
Чёрные иконки были хороши на белом / почти белом фоне. На чёрном же фоне потребуются светлые.
К счастью, System.Drawing.Bitmap
является изменяемым типом, поэтому ничто не мешает нам при изменении системных цветов перерисовать непосредственно используемый Bitmap.
Главное подобрать разумный алгоритм адаптации иконки под цветовую схему.
Казалось бы, пора поздравить себя с успехом и заняться другими делами, но не тут-то было. Мне нравится новый вид моего приложения, мысль о его потенциальном разнообразии греет душу, но чтобы пользоваться этим, нужно менять скин Windows. Это какой-то неправильный успех.
Скин
Нельзя ли, пользуясь проделанной ранее работой, реализовать настраиваемую цветовую схему отдельно для приложения? Хочется использовать SystemColors
и дальше, так как он
- поддерживается DesignTime редактором в Visual Studio
- используется самим .NET Framework и Win32 API
Таким образом, новые элементы, добавляемые в UI смогут учитывать цвета скина без дополнительных усилий при разработке.
System.Drawing.Color
Рассмотрим реализацию структуры System.Drawing.Color
в исходном коде .NET Framework
Структура System.Drawing.Color
реализует 2 способа поведения.
- Хранить байты цвета непосредственно
- Получать из таблицы
KnownColorsTable
по значению перечисленияKnownColor
KnownColorsTable
хранит значения системных цветов в приватном массиве colorTable
, содержимое которого по мере необходимости обновляется с использованием запросов Win32 API.
Нам достаточно подменять значения в colorTable
, чтобы для нашего приложения системные цвета имели такие значения, как нам нужно.
Вот как это было сделано.
На скриншоте ниже контекстное меню, которое сходу правильно отображается с изменёнными цветами:
Для быстрого редактирования цветовой схемы был реализован простой редактор:
Нативно рисуемые контролы
Некоторые элементы UI из .NET Framework будут игнорировать подмену SystemColors
, потому что они рисуют себя полностью за счёт запросов Win32 API. Характерный и распространённый пример - System.Windows.Forms.ScrollBar
. То же отчасти относится и к ListView
, TreeView
, ComboBox
и так далее.
ScrollBar
В случае ScrollBar
ничего не остаётся, как сделать свой. Я нашёл хорошую реализацию, с небольшим количеством исправлений и улучшений получился вполне приличный вариант.
ComboBox
Большую часть недостатков отрисовки ComboBox можно решить переносом кода отображения в .NET framework, это можно сделать единообразно.
Но и в этих деталях есть дьявол - границу выпадающего списка, в том числе скролл выпадающего списка, так просто не победить.
RichTextBox
По-видимому, он имеет собственный кеш цвета, потому что простой Invalidate()
не приводит к перерисовке с изменённым SystemColor
. Также не помогает переустановка BackColor
/ ForeColor
, потому что он умный и замечает, что как был SystemColors.WindowText
, так и остался.
Немного дополнительной настойчивости всё же заставит его склониться перед вашей волей.
Итоги
Ценой умеренных усилий, около 4 человеко-дней, удалось решить следующие задачи:
- Весь UI отображается с учётом системных цветов Windows
- Реализован простой, но достаточный UI для редактирования цветовой схемы приложения.
- Подавляющая часть UI допускает применение цветов из редактируемой цветовой схемы приложения.
- Монохромные иконки приложения адаптируются к цветовой схеме и хорошо различимы при условии адекватности самой схемы.
- Как и раньше, можно редактировать цвета в DesignTime WinForms редакторе Visual Studio, не пришлось вводить отдельную сущность для цветовой схемы приложения отдельно от цветовой схемы Windows.
- В моём приложении теперь есть своя Тёмная цветовая схема 😎
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.