При разработке интерфейсов на управляемых формах в среде «1С:Предприятие 8» часто возникает задача отображения графической информации. Платформа предоставляет для этого стандартный элемент — поле картинки, которое отлично справляется со своей задачей. Более того, в контекстном меню этого поля по умолчанию присутствует полезная команда «Просмотреть картинку». При её активации открывается удобное окно с возможностью масштабирования и детального изучения изображения.
Однако разработчики часто сталкиваются с ограничением: этой команды нет в списке стандартных команд формы на вкладке «Команды». Соответственно, её невозможно просто перетащить на командную панель формы или назначить кнопке. Пользователю приходится кликать правой кнопкой мыши и искать пункт в контекстном меню, что не всегда удобно и интуитивно понятно.
В данной статье мы разберем, как программно обойти это ограничение, запустить стандартный просмотрщик по обычному клику на картинку или при нажатии произвольной кнопки, а также рассмотрим особенности работы с временным хранилищем и асинхронными вызовами в современных версиях платформы.
В старых версиях платформы (в обычных формах) для решения подобной задачи использовался синхронный метод ОткрытьЗначение(). Код выглядел следующим образом:
Процедура ПросмотрКартинки(Элемент)
ОткрытьЗначение(ЭлементыФормы.МояКартинка.Картинка);
КонецПроцедуры
Важное предупреждение: Использование метода ОткрытьЗначение() в современном управляемом приложении крайне не рекомендуется. Если в свойствах вашей конфигурации параметр «Режим использования модальности» установлен в значение «Не использовать» (что является стандартом для всех современных решений), то вызов этого метода на клиенте вызовет ошибку выполнения. В управляемом интерфейсе на смену ему пришел асинхронный метод ПоказатьЗначение().
Проанализируем детально, как организовать полный жизненный цикл работы с изображением в управляемой форме. Нам понадобится реквизит объекта (например, справочника) с типом ХранилищеЗначения (назовем его ХранилищеКартинки) и реквизит управляемой формы с типом Строка (назовем его АдресКартинки), который мы свяжем с полем картинки на форме.
Разберем по шагам серверную логику чтения и записи данных:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Помещаем картинку из Хранилища Значения во Временное Хранилище.
// Обязательно привязываем её к Уникальному Идентификатору формы!
АдресКартинки = ПоместитьВоВременноеХранилище(ТекущийОбъект.ХранилищеКартинки.Получить(), УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Перед записью извлекаем данные из временного хранилища обратно в объект базы данных
Если ЭтоАдресВременногоХранилища(АдресКартинки) Тогда
ТекущийОбъект.ХранилищеКартинки = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(АдресКартинки), Новый СжатиеДанных(9));
ИначеЕсли АдресКартинки = "" Тогда
ТекущийОбъект.ХранилищеКартинки = Неопределено;
КонецЕсли;
КонецПроцедуры
Теперь рассмотрим интерактивную часть на клиенте: загрузку нового файла и очистку поля:
&НаКлиенте
Процедура ЗагрузитьКартинку(Команда)
// Инициируем выбор файла на клиенте асинхронным методом
НачатьПомещениеФайла(Новый ОписаниеОповещения("ЗагрузитьКартинкуЗавершение", ЭтотОбъект), , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузитьКартинкуЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Результат = Истина Тогда
АдресКартинки = Адрес;
Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьКартинку(Команда)
АдресКартинки = "";
Модифицированность = Истина;
КонецПроцедуры
Для того чтобы окно просмотра открывалось при обычном нажатии левой кнопкой мыши на область картинки, нам необходимо переопределить стандартное событие поля картинки Нажатие. Создадим для этого элемента обработчик события и напишем следующий код:
&НаКлиенте
Процедура АдресКартинкиНажатие(Элемент, СтандартнаяОбработка)
// Отменяем стандартное поведение системы, чтобы не открывалось дефолтное меню
СтандартнаяОбработка = Ложь;
// Проверяем, загружено ли изображение в хранилище
Если ЗначениеЗаполнено(АдресКартинки) Тогда
// Создаем объект Картинка на основе двоичных данных из Временного Хранилища
// и передаем его в асинхронный метод ПоказатьЗначение()
ПоказатьЗначение(, Новый Картинка(ПолучитьИзВременногоХранилища(АдресКартинки)));
КонецЕсли;
КонецПроцедуры
В этом обработчике мы принудительно устанавливаем свойство СтандартнаяОбработка = Ложь. Это предотвращает стандартный отклик платформы на клик и позволяет нам запустить собственный алгоритм. Мы конструируем новый объект Картинка, считывая двоичные данные по адресу временного хранилища, и передаем его в метод ПоказатьЗначение(). Первым параметром мы указываем Неопределено, так как нам не нужно выполнять никаких действий на клиенте после закрытия пользователем окна просмотра.
Для создания надежного и стабильного решения обратим внимание на важные архитектурные особенности платформы «1С:Предприятие»:
УникальныйИдентификатор формы при вызовах функций ПоместитьВоВременноеХранилище() и НачатьПомещениеФайла(). Если этого не сделать, то при первом же серверном вызове (например, при автосохранении или пересчете других реквизитов) данные во временном хранилище будут очищены платформой. В результате при попытке просмотра пользователь увидит пустую форму.ПоказатьЗначение(). Теперь открывающееся системное окно оснащено полноценной панелью инструментов (масштабирование, сохранение файла на диск, печать) и полностью идентично окну, которое вызывается через контекстное меню.ПоказатьЗначение() для тяжелых картинок может вести себя нестабильно из-за внутренних политик безопасности веб-браузеров. Если ваше решение активно используется в веб-клиенте, в качестве альтернативы можно использовать поле HTML-документа для отображения картинок или предлагать пользователю скачать файл на локальный компьютер через метод ПолучитьФайл().Используя предложенное решение, мы успешно обошли платформенное ограничение, перенеся удобную команду просмотра изображения непосредственно на событие клика по картинке, что существенно улучшает юзабилити разрабатываемой конфигурации.