Как-то мне понадобилось сделать однотонные цветные закладки, чтобы пользователь мог сам выбирать цвет. Стандартный функционал 1С страниц панели, поддерживает только присвоение объекта типа Картинка для закладок. Возможно, есть решение в объектах ActiveX, но моя душа к такому способу не лежала. Но как говорится, если гора идет к Магомету, то Магомет идет к горе. Поэтому решил создать объект типа Картинка программно.
Для этого идеально подошел формат BMP (как самый простейший из форматов хранения изображений). Чтобы не заморачиваться с палитрой, выбрал 24-битную глубину изображения (байты цвета каждого пикселя хранятся в порядке Blue,Green,Red). Затем, не мудрствуя лукаво, создал однотонную картинку 16×16 в паинте и вооружившись HEX-редактором перенес оттуда заполненные поля заголовка файла в код 1С, который заполняет массив данных. Чтобы записать массив в бинарный файл, запихиваем его в COMSafeArray, который уже с помощью потока COMОбъекта «ADODB.Stream» сохраняем в файл.
Таким образом, путем нехитрых манипуляций родилась небольшая функция:
Функция СоздатьКартинку(Цвет)
Данные = Новый Массив(822);
// Заполняем заголовок файла служебной информацией
Данные[0] = 66; Данные[1] = 77;
Данные[2] = 54; Данные[3] = 03;
Данные[10] = 54; Данные[14] = 40;
Данные[18] = 16; Данные[22] = 16;
Данные[26] = 01; Данные[28] = 24;
Данные[38] = 195; Данные[39] = 14;
Данные[42] = 195; Данные[43] = 14;
// Заполняем всю картинку выбранным цветом
// Единственный косяк в том, что нельзя выбрать ни WebЦвета, ни Windows
// Как вариант, можно выбрать цвет на вкладке WevЦвета или Windows, затем перейдя на вкладку «из стиля»
// поменять значение любого компонента цвета (красный, зеленый, синий) и вернуть его обратно
Для Счетчик = 0 По 255 Цикл
Данные[54 + Счетчик * 3] = Цвет.Синий;
Данные[54 + Счетчик * 3 + 1] = Цвет.Зеленый;
Данные[54 + Счетчик * 3 + 2] = Цвет.Красный;
КонецЦикла;
// Обводим рамочкой и не забываем, что строки в bmp-файле хранятся снизу-вверх
Для Счетчик = 0 По 15 Цикл
// рамка снизу
Данные[54 + Счетчик * 3] = 0; Данные[55 + Счетчик * 3] = 0; Данные[56 + Счетчик * 3] = 0;
// рамка сверху
Данные[773 + Счетчик * 3] = 0; Данные[774 + Счетчик * 3] = 0; Данные[775 + Счетчик * 3] = 0;
// рамка слева
Данные[54 + Счетчик * 48] = 0; Данные[55 + Счетчик * 48] = 0; Данные[56 + Счетчик * 48] = 0;
// рамка справа
Данные[ 99 + Счетчик * 48] = 0; Данные[100 + Счетчик * 48] = 0; Данные[101 + Счетчик * 48] = 0;
КонецЦикла;
// Создаем bmp-файл
ИмяФайла = ПолучитьИмяВременногоФайла(«bmp»);
Поток = Новый COMОбъект(«ADODB.Stream»);
Поток.Type = 1;
Поток.Mode = 3;
Поток.Open();
Поток.Write(Новый COMSafeArray(Данные, «VT_UI1», Данные.Количество()));
Поток.SaveToFile(ИмяФайла);
Поток.Close();
Возврат Новый Картинка(Новый ДвоичныеДанные(ИмяФайла));
КонецФункции
Вот и все. Только пришлось добавить рамочку вокруг рисунка для красоты 🙂
очень интересно. я делал обработку для создания не только монотонных рисунковhttp://infostart.ru/public/77713/
проще было бы, конечно, использовать ком объект потока, но хотелось все чисто внутренними методами 1С
а так, беру на заметку
Там же целый минипаинт 🙂 А тут маленькая функция для создания иконки. Но, как говорится, на вкус и цвет… 🙂
Хорошая и полезная тема с отличными комментариями. Как-то недавно пришлось столкнуться как можно из библиотеки картинок извлечь таким-же макаром отдельные картинки — перепахал весь код и ускорил в 10 раз, хотя помучаться прищлось, необычные методики для 1С. Вот все никак на статью не разрожусь.
C COMSafeArray неплохо придумал, надо будет взять на вооружение.
Как раз, то что нужно!
не проверял на 1С-цвета ) поставил заглушку, если пользователь выберет цвет из 1Совских через ДиалогВыбораЦвета.
Функция ПолучитьRGB(Цвет) Экспорт
Попытка
фд = Новый ФорматированныйДокумент;
тфд = фд.Добавить(«Текст», Тип(«ТекстФорматированногоДокумента»));
тфд.ЦветТекста = Цвет;
Если (Цвет.Вид <> ВидЦвета.Абсолютный) И (Цвет.Вид <> ВидЦвета.WebЦвет) Тогда
тфд.ЦветТекста = WebЦвета.Белый;//неизвестные цвета пусть будут белыми
КонецЕсли;
тмл = «»;
фд.ПолучитьHTML(хтмл, Новый Структура);
Исключение
Сообщить(«Ошибка при построении служебного форматированного документа: » + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Попытка
рЧтение = Новый ЧтениеHTML;
рЧтение.УстановитьСтроку(хтмл);
пострДом = Новый ПостроительDOM;
докДом = пострДом.Прочитать(рЧтение);
знчАтрибута = докДом.Тело.ДочерниеУзлы[1].ПервыйДочерний.Атрибуты[0].Значение;
рЦвет16ричный = СокрЛП(СтрЗаменить(СтрЗаменить(знчАтрибута, «color: «, «»), «;», «»));
Исключение
Сообщить(«Ошибка при распознании содержания форматированного документа: » + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Возврат ПолучитьRGBИз16(рЦвет16ричный);
КонецФункции