Как программно добавить поле картинки в расширении 1С и настроить обработчик нажатия?

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

При разработке в расширениях «1С:Предприятие 8.3» программисты часто сталкиваются с задачей динамического изменения интерфейса. Типичный пример — необходимость добавить на форму элемента справочника или документа поле для отображения логотипа контрагента, фотографии сотрудника или изображения номенклатуры. Однако при программном создании элементов интерфейса возникает серьезное препятствие: привязка обработчиков событий (таких как нажатие или изменение) часто не срабатывает, возвращая стандартные системные окна вместо вызова кастомного кода.

В этой статье мы подробно разберем, почему платформа ведет себя подобным образом, как правильно связать динамический элемент формы с кодом в расширении, а также рассмотрим несколько альтернативных способов решения этой задачи.

Выясняем причину: почему не работает УстановитьДействие?

В управляемом приложении 1С метод УстановитьДействие (или свойство Действие у программно добавляемых команд) имеет жесткое платформенное ограничение. В качестве второго параметра этот метод принимает исключительно строковое имя экспортируемой процедуры, расположенной строго в модуле самой этой формы.

Попытка передать туда конструкцию вида "ИмяОбщегоМодуля.ИмяПроцедуры" или настроить вызов процедуры, находящейся в общем модуле расширения, ни к чему не приведет. Платформа просто проигнорирует этот вызов или выдаст ошибку, так как контекст исполнения события жестко изолирован внутри конкретной формы. Именно поэтому у автора темы нажатие по картинке вызывало стандартное системное окно, а не его кастомную процедуру.

Для решения этой проблемы существует три основных метода. Разберем их по шагам.

---

Решение 1: Классический метод с «легким» заимствованием формы

Наиболее надежный и стандартный способ — заимствовать целевую форму в расширение, чтобы получить доступ к ее модулю, но сделать это максимально «аккуратно», чтобы не усложнить будущие обновления конфигурации.

Многие разработчики боятся переносить формы в расширение, предполагая, что это повлечет за собой заимствование всех связанных реквизитов и перегрузит конфигурацию. На самом деле существует безопасная методика «легкого заимствования»:

  1. Добавляем нужную форму (например, ФормаЭлемента справочника Контрагенты) в расширение.
  2. Открываем редактор формы в расширении, выделяем абсолютно все элементы и реквизиты в деревьях формы и удаляем их. Наша форма в расширении становится абсолютно пустой «пустышкой».
  3. При этом в пользовательском режиме форма будет отрисовываться в своем стандартном виде со всеми реквизитами из основной конфигурации. Наше расширение теперь хранит только «скелет» формы и ее модуль, что гарантирует бесконфликтное обновление системы в будущем.

После этого мы можем переходить к написанию кода. Реализуем программное добавление реквизита, элемента формы и подключение события.

Шаг 1. В общем модуле расширения перехватываем событие создания формы на сервере с помощью аннотации &После:


&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
    
    // Проверяем, что работаем с нужной формой
    Если Форма.ИмяФормы = "Справочник.Контрагенты.Форма.ФормаЭлемента" Тогда
        
        // 1. Создаем и добавляем новый реквизит формы для хранения пути к картинке
        ДобавляемыеРеквизиты = Новый Массив;
        РеквизитЛоготип = Новый РеквизитФормы("Расш1_Логотип", Новый ОписаниеТипов("Строка"), , "Логотип");
        ДобавляемыеРеквизиты.Добавить(РеквизитЛоготип);
        Форма.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
        
        // 2. Программно создаем элемент формы "ПолеКартинки"
        Элементы = Форма.Элементы;
        // Добавляем элемент в существующую на форме группу (например, ГруппаОбщаяИнформация)
        ЭлементКартинка = Элементы.Добавить("Расш1_Логотип", Тип("ПолеФормы"), Элементы.ГруппаОбщаяИнформация);
        ЭлементКартинка.Вид = ВидПоляФормы.ПолеКартинки;
        ЭлементКартинка.ПутьКДанным = "Расш1_Логотип";
        ЭлементКартинка.Заголовок = "Логотип контрагента";
        ЭлементКартинка.Гиперссылка = Истина;
        ЭлементКартинка.Доступность = Истина;
        ЭлементКартинка.Видимость = Истина;
        
        // 3. Связываем событие "Нажатие" с процедурой, которую мы разместим в модуле заимствованной формы
        ЭлементКартинка.УстановитьДействие("Нажатие", "Расш1_ЛоготипНажатие");
        
    КонецЕсли;
    
КонецПроцедуры

Шаг 2. В модуле нашей заимствованной («легкой») формы в расширении пишем клиентские обработчики для работы с файлом картинки. Будем использовать современные асинхронные методы платформы 1С:


&НаКлиЕнте
Процедура Расш1_ЛоготипНажатие(Элемент, СтандартнаяОбработка)
    
    // Отменяем стандартное поведение платформы
    СтандартнаяОбработка = Ложь;
    
    // Создаем описание оповещения для обработки выбора файла
    ОписаниеОповещения = Новый ОписаниеОповещения("Расш1_ОбработатьВыборФайлаКартинки", ЭтотОбъект);
    
    // Настраиваем диалог выбора файла изображения
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ДиалогОткрытияФайла.Фильтр = "Файлы картинок (*.jpg;*.png;*.jpeg)|*.jpg;*.png;*.jpeg";
    ДиалогОткрытияФайла.Заголовок = "Выберите файл логотипа для загрузки";
    ДиалогОткрытияФайла.ПредварительныйПросмотр = Истина;
    ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
    
    // Запускаем асинхронное помещение файла во временное хранилище
    НачатьПомещениеФайлов(ОписаниеОповещения, , ДиалогОткрытияФайла, Истина, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура Расш1_ОбработатьВыборФайлаКартинки(ПомещенныеФайлы, ДопПараметры) Экспорт
    
    // Проверяем, выбрал ли пользователь файл
    Если ПомещенныеФайлы = Неопределено Или ПомещенныеФайлы.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем адрес временного хранилища, куда платформа поместила файл
    АдресКартинкиВХранилище = ПомещенныеФайлы[0].Хранение;
    
    // Записываем адрес в наш реквизит формы, чтобы картинка отобразилась на форме
    ЭтотОбъект.Расш1_Логотип = АдресКартинкиВХранилище;
    
    // Сигнализируем системе, что данные формы были изменены
    ЭтотОбъект.Модифицированность = Истина;
    
КонецПроцедуры

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

---

Решение 2: Использование декораций и навигационных ссылок (без заимствования формы)

Рассмотрим альтернативную ситуацию: что делать, если вам категорически запрещено заимствовать форму в расширение? В платформе 1С есть интересная возможность обойти это ограничение с помощью элемента ДекорацияФормы.

Вместо элемента ПолеФормы с видом ПолеКартинки мы можем программно создать декорацию-картинку и использовать механизм навигационных ссылок. Платформа умеет обрабатывать нажатия на такие ссылки самостоятельно, минуя необходимость писать код в модуле формы.

Проанализируем пример реализации такого подхода в общем модуле расширения:


&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
    
    Если Форма.ИмяФормы = "Справочник.Контрагенты.Форма.ФормаЭлемента" Тогда
        
        Элементы = Форма.Элементы;
        
        // Создаем декорацию формы типа Картинка
        ЭлементДекорация = Элементы.Добавить("Расш1_ДекорацияЛоготип", Тип("ДекорацияФормы"), Элементы.ГруппаОбщаяИнформация);
        ЭлементДекорация.Вид = ВидДекорацииФормы.Картинка;
        
        // Устанавливаем стандартную картинку из библиотеки или адрес из базы данных
        ЭлементДекорация.Картинка = БиблиотекаКартинок.ВыбратьФайл;
        ЭлементДекорация.Гиперссылка = Истина;
        
        // Указываем навигационную ссылку. При клике платформа выполнит переход или вызовет команду.
        // Это может быть ссылка на внешнюю обработку, команду БСП или элемент файлового хранилища.
        ЭлементДекорация.НавигационнаяСсылка = "e1cib/app/Справочник.ШаблоныСообщений..."; 
        
    КонецЕсли;
    
КонецПроцедуры

Этот способ имеет ограничения по логике обработки события, но идеально подходит для задач в стиле «открыть файл по клику» или «перейти по ссылке», полностью исключая необходимость расширения модулей форм.

---

Решение 3: Подключаемые команды БСП (Библиотеки Стандартных Подсистем)

Если ваша конфигурация разработана на современной ERP 2.5, Комплексной автоматизации или Управлении торговлей, то в ней гарантированно используется БСП. Практически на каждой управляемой форме этих конфигураций уже присутствует встроенный механизм динамического подключения команд.

Мы можем интегрировать свою команду выбора картинки в штатный механизм БСП, используя переопределяемые общие модули конфигурации (например, ПриОпределенииКомандПодключенныхКОбъектам). Схема работы выглядит следующим образом:

  1. В общем модуле расширения регистрируем нашу команду для справочника Партнеры.
  2. БСП автоматически выведет кнопку на форму элемента.
  3. При нажатии на эту кнопку управление уйдет в штатную процедуру формы Подключаемый_ВыполнитьКоманду.
  4. Штатный обработчик БСП перенаправит вызов в наш общий модуль в расширении.

Этот метод является наиболее методологически верным с точки зрения стандартов разработки фирмы «1С» для типовых конфигураций, так как он полностью исключает ручное заимствование форм и написание кода «в обход» стандартов БСП.

---

Сводная таблица решений

Резюмируем, какой из подходов выбрать в зависимости от ваших задач:

Метод решения Плюсы Минусы
«Легкое» заимствование формы Полная свобода написания кода на клиенте, поддержка любых асинхронных диалогов и сложных обработчиков. Форма все же заимствуется в расширение (хотя и в минимальном объеме).
Декорация с навигационной ссылкой Не требует заимствования формы вообще, создается полностью «на лету» из общего модуля. Ограниченный функционал интерактивного взаимодействия.
Подключаемые команды БСП Соответствие стандартам 1С совместимо, стабильность при любых масштабных обновлениях ERP. Требует детального понимания архитектуры БСП и написания интеграционного кода.

Используя предложенные методики, вы сможете эффективно решать задачи по динамическому управлению интерфейсом в расширениях 1С, сохраняя чистоту кода и обеспечивая легкую поддержку ваших конфигураций.

← На главную