В процессе разработки интерфейсов на платформе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью дать пользователю возможность выбрать цвет (например, для выделения строк в отчете или настройки элементов формы). Однако стандартный ДиалогВыбораЦвета иногда ведет себя неожиданно: вместо привычных значений интенсивности каналов (от 0 до 255) свойства Красный, Зеленый и Синий возвращают значение -1. Разберем по шагам, почему это происходит и как правильно работать с цветами в системе.
Рассмотрим ситуацию, которую описал автор вопроса. Типичный код вызова диалога выглядит следующим образом:
Диалог = Новый ДиалогВыбораЦвета;
Если Диалог.Выбрать() Тогда
// Ошибка в логике обращения к свойствам
ВыбранныйЦвет = Диалог.Цвет; // В исходном коде было .Вид, что неверно
Красный = ВыбранныйЦвет.Красный;
Зеленый = ВыбранныйЦвет.Зеленый;
Синий = ВыбранныйЦвет.Синий;
КонецЕсли;
Проанализируем ситуацию: если пользователь выбирает цвет на закладке «Абсолютные», то всё работает корректно. Но стоит выбрать цвет из категорий «Web» или «Системные», как переменные принимают значение -1. Выясним причину такого поведения системы, обратившись к логике работы объекта Цвет.
В системе «1С:Предприятие» объект Цвет может принадлежать к одному из четырех видов. Это критически важно понимать для корректного извлечения данных:
Красный, Зеленый и Синий вернут значения в диапазоне 0–255.Важный момент: Если цвет не является Абсолютным, платформа не вычисляет его RGB-составляющие «на лету» при обращении к свойствам, а возвращает -1. Это логично, так как системный цвет может измениться в любой момент при смене темы Windows, и фиксированное число в коде 1С стало бы неактуальным.
В коде автора была допущена ошибка: ВыбранныйЦвет = Диалог.Цвет.Вид;. Свойство Вид возвращает значение системного перечисления (например, ВидЦвета.Абсолютный), а не сам объект цвета. Чтобы получить доступ к каналам, нужно работать непосредственно с объектом Цвет, который возвращает Диалог.Цвет.
Если ваша задача — просто сохранить выбор пользователя в базу данных (в справочник или настройки), чтобы потом применить его к элементу формы, самый правильный и простой способ — использовать ХранилищеЗначения. Рассмотрим пример:
// Запись цвета в реквизит объекта (тип реквизита - ХранилищеЗначения)
Диалог = Новый ДиалогВыбораЦвета;
Если Диалог.Выбрать() Тогда
Объект.РеквизитЦвет = Новый ХранилищеЗначения(Диалог.Цвет);
КонецЕсли;
// Восстановление цвета при открытии формы
ЦветИзБазы = Объект.РеквизитЦвет.Получить();
Если ТипЗнч(ЦветИзБазы) = Тип("Цвет") Тогда
ЭлементыФормы.ПолеВвода1.ЦветТекста = ЦветИзБазы;
КонецЕсли;
Этот метод универсален. Он сохранит и RGB-значение, и имя Web-цвета, и ссылку на Системный цвет. При смене темы оформления системные цвета будут обновляться автоматически, так как в базе хранится именно ссылка на тип цвета, а не «замороженные» числа.
Иногда нам все же необходимо получить именно числа (например, для передачи цвета на сторонний сайт через API или генерации CSS-стилей). Рассмотрим подробнее, как «вытащить» RGB из неабсолютного цвета. Прямого метода ПреобразоватьВАбсолютный() в старых версиях платформы нет, но мы можем использовать механизмы сериализации.
Проанализируем ситуацию с использованием внутреннего формата 1С:
// Пример получения RGB через ЗначениеВСтрокуВнутр
Функция ПолучитьRGB(ВыбранныйЦвет)
// Для абсолютного цвета возвращаем сразу
Если ВыбранныйЦвет.Вид = ВидЦвета.Абсолютный Тогда
Возврат СтрШаблон("%1, %2, %3", ВыбранныйЦвет.Красный, ВыбранныйЦвет.Зеленый, ВыбранныйЦвет.Синий);
КонецЕсли;
// Пытаемся сериализовать объект
СтрокаВнутр = ЗначениеВСтрокуВнутр(ВыбранныйЦвет);
// Строка будет иметь вид типа {"#",b633e143-84c0-4887-8672-313931d8849c, 0, 100, 150, 200}
// Где последние три числа часто соответствуют RGB
// (Метод требует осторожности и парсинга строки)
Возврат "Метод требует ручного разбора строки";
КонецФункции
Если использование ХранилищеЗначения кажется избыточным (например, нужно хранить тысячи строк с цветами), можно упаковать абсолютный цвет в обычное числовое поле. Разберем по шагам формулу упаковки:
Формула: ЦветЧислом = Красный + (Зеленый * 256) + (Синий * 65536);
Для реализации этого метода нам нужно гарантировать, что цвет абсолютный. Если пользователь выбрал системный цвет, мы можем попытаться сопоставить его или просто выдать предупреждение.
Если Диалог.Выбрать() Тогда
Если Диалог.Цвет.Вид = ВидЦвета.Абсолютный Тогда
ЦветЧислом = Диалог.Цвет.Красный + Диалог.Цвет.Зеленый * 256 + Диалог.Цвет.Синий * 65536;
// Сохраняем ЦветЧислом в реквизит типа Число(10,0)
Иначе
Сообщить("Пожалуйста, выберите цвет на закладке 'Абсолютные'");
КонецЕсли;
КонецЕсли;
Для работы с Web-технологиями удобнее использовать формат HEX (например, #FF5733). Рассмотрим пример функции преобразования:
Функция ЦветВHex(ВыбранныйЦвет)
Если ВыбранныйЦвет.Вид <> ВидЦвета.Абсолютный Тогда
Возврат "#000000"; // Либо логика обработки неабсолютных цветов
КонецЕсли;
Возврат "#" + СтрРегистр(КрасныйВHex(ВыбранныйЦвет.Красный) + ...);
КонецФункции
Мы выяснили, что получение -1 — это не ошибка платформы, а следствие работы с объектной моделью цветов. В 1С цвет — это не всегда три числа, это может быть ссылка на системную настройку. Для большинства задач внутри 1С идеальным решением будет использование ХранилищаЗначения. Если же требуется интеграция с внешними системами — используйте проверку ВидЦвета.Абсолютный и ручную конвертацию в RGB или HEX.
Помните, что при работе в современных версиях платформы (8.3.15+) и в интерфейсе «Такси», системные цвета могут вести себя по-разному в зависимости от того, включена ли темная тема. Поэтому сохранение именно «объекта» цвета предпочтительнее сохранения его числовых составляющих.