Почему ДиалогВыбораЦвета возвращает -1 и как получить RGB-значения цвета в 1С

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

В процессе разработки интерфейсов на платформе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью дать пользователю возможность выбрать цвет (например, для выделения строк в отчете или настройки элементов формы). Однако стандартный ДиалогВыбораЦвета иногда ведет себя неожиданно: вместо привычных значений интенсивности каналов (от 0 до 255) свойства Красный, Зеленый и Синий возвращают значение -1. Разберем по шагам, почему это происходит и как правильно работать с цветами в системе.

Анализ исходной проблемы

Рассмотрим ситуацию, которую описал автор вопроса. Типичный код вызова диалога выглядит следующим образом:


Диалог = Новый ДиалогВыбораЦвета; 
        
Если Диалог.Выбрать() Тогда 
    // Ошибка в логике обращения к свойствам
    ВыбранныйЦвет = Диалог.Цвет; // В исходном коде было .Вид, что неверно
    
    Красный = ВыбранныйЦвет.Красный;
    Зеленый = ВыбранныйЦвет.Зеленый;
    Синий = ВыбранныйЦвет.Синий;        
КонецЕсли;

Проанализируем ситуацию: если пользователь выбирает цвет на закладке «Абсолютные», то всё работает корректно. Но стоит выбрать цвет из категорий «Web» или «Системные», как переменные принимают значение -1. Выясним причину такого поведения системы, обратившись к логике работы объекта Цвет.

Типы цветов в платформе 1С

В системе «1С:Предприятие» объект Цвет может принадлежать к одному из четырех видов. Это критически важно понимать для корректного извлечения данных:

  1. Абсолютный: Цвет задается жестко тремя числами (RGB). Только в этом случае свойства Красный, Зеленый и Синий вернут значения в диапазоне 0–255.
  2. Web-цвет: Цвет выбирается из стандартного набора именованных цветов HTML (например, «AliceBlue» или «Gold»). Платформа хранит его имя, а не числовой код.
  3. Цвет стиля: Цвет привязан к метаданным конфигурации (например, «Цвет отрицательного числа»). Его реальное значение зависит от настроек конкретной темы оформления.
  4. Системный цвет Windows: Цвет, определяемый настройками операционной системы (например, «Цвет фона рабочего стола» или «Цвет текста кнопки»).

Важный момент: Если цвет не является Абсолютным, платформа не вычисляет его RGB-составляющие «на лету» при обращении к свойствам, а возвращает -1. Это логично, так как системный цвет может измениться в любой момент при смене темы Windows, и фиксированное число в коде 1С стало бы неактуальным.

Исправление логической ошибки в коде

В коде автора была допущена ошибка: ВыбранныйЦвет = Диалог.Цвет.Вид;. Свойство Вид возвращает значение системного перечисления (например, ВидЦвета.Абсолютный), а не сам объект цвета. Чтобы получить доступ к каналам, нужно работать непосредственно с объектом Цвет, который возвращает Диалог.Цвет.

Решение 1: Сохранение через ХранилищеЗначения

Если ваша задача — просто сохранить выбор пользователя в базу данных (в справочник или настройки), чтобы потом применить его к элементу формы, самый правильный и простой способ — использовать ХранилищеЗначения. Рассмотрим пример:


// Запись цвета в реквизит объекта (тип реквизита - ХранилищеЗначения)
Диалог = Новый ДиалогВыбораЦвета;
Если Диалог.Выбрать() Тогда
    Объект.РеквизитЦвет = Новый ХранилищеЗначения(Диалог.Цвет);
КонецЕсли;

// Восстановление цвета при открытии формы
ЦветИзБазы = Объект.РеквизитЦвет.Получить();
Если ТипЗнч(ЦветИзБазы) = Тип("Цвет") Тогда
    ЭлементыФормы.ПолеВвода1.ЦветТекста = ЦветИзБазы;
КонецЕсли;

Этот метод универсален. Он сохранит и RGB-значение, и имя Web-цвета, и ссылку на Системный цвет. При смене темы оформления системные цвета будут обновляться автоматически, так как в базе хранится именно ссылка на тип цвета, а не «замороженные» числа.

Решение 2: Принудительная конвертация в RGB (Сериализация)

Иногда нам все же необходимо получить именно числа (например, для передачи цвета на сторонний сайт через API или генерации CSS-стилей). Рассмотрим подробнее, как «вытащить» RGB из неабсолютного цвета. Прямого метода ПреобразоватьВАбсолютный() в старых версиях платформы нет, но мы можем использовать механизмы сериализации.

Проанализируем ситуацию с использованием внутреннего формата 1С:


// Пример получения RGB через ЗначениеВСтрокуВнутр
Функция ПолучитьRGB(ВыбранныйЦвет)
    
    // Для абсолютного цвета возвращаем сразу
    Если ВыбранныйЦвет.Вид = ВидЦвета.Абсолютный Тогда
        Возврат СтрШаблон("%1, %2, %3", ВыбранныйЦвет.Красный, ВыбранныйЦвет.Зеленый, ВыбранныйЦвет.Синий);
    КонецЕсли;
    
    // Пытаемся сериализовать объект
    СтрокаВнутр = ЗначениеВСтрокуВнутр(ВыбранныйЦвет);
    // Строка будет иметь вид типа {"#",b633e143-84c0-4887-8672-313931d8849c, 0, 100, 150, 200}
    // Где последние три числа часто соответствуют RGB
    // (Метод требует осторожности и парсинга строки)
    
    Возврат "Метод требует ручного разбора строки";
КонецФункции

Решение 3: Упаковка цвета в число или HEX-строку

Если использование ХранилищеЗначения кажется избыточным (например, нужно хранить тысячи строк с цветами), можно упаковать абсолютный цвет в обычное числовое поле. Разберем по шагам формулу упаковки:

Формула: ЦветЧислом = Красный + (Зеленый * 256) + (Синий * 65536);

Для реализации этого метода нам нужно гарантировать, что цвет абсолютный. Если пользователь выбрал системный цвет, мы можем попытаться сопоставить его или просто выдать предупреждение.


Если Диалог.Выбрать() Тогда
    Если Диалог.Цвет.Вид = ВидЦвета.Абсолютный Тогда
        ЦветЧислом = Диалог.Цвет.Красный + Диалог.Цвет.Зеленый * 256 + Диалог.Цвет.Синий * 65536;
        // Сохраняем ЦветЧислом в реквизит типа Число(10,0)
    Иначе
        Сообщить("Пожалуйста, выберите цвет на закладке 'Абсолютные'");
    КонецЕсли;
КонецЕсли;

Для работы с Web-технологиями удобнее использовать формат HEX (например, #FF5733). Рассмотрим пример функции преобразования:


Функция ЦветВHex(ВыбранныйЦвет)
    Если ВыбранныйЦвет.Вид <> ВидЦвета.Абсолютный Тогда
        Возврат "#000000"; // Либо логика обработки неабсолютных цветов
    КонецЕсли;
    
    Возврат "#" + СтрРегистр(КрасныйВHex(ВыбранныйЦвет.Красный) + ...); 
КонецФункции

Подведение итогов

Мы выяснили, что получение -1 — это не ошибка платформы, а следствие работы с объектной моделью цветов. В 1С цвет — это не всегда три числа, это может быть ссылка на системную настройку. Для большинства задач внутри 1С идеальным решением будет использование ХранилищаЗначения. Если же требуется интеграция с внешними системами — используйте проверку ВидЦвета.Абсолютный и ручную конвертацию в RGB или HEX.

Помните, что при работе в современных версиях платформы (8.3.15+) и в интерфейсе «Такси», системные цвета могут вести себя по-разному в зависимости от того, включена ли темная тема. Поэтому сохранение именно «объекта» цвета предпочтительнее сохранения его числовых составляющих.

← На главную