Программные формы
















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

Подсистема рассчитана на обычные, не управляемые формы. Несмотря на то, что технология обычных форм устарела, все еще есть конфигурации, поставляемые на обычных формах (например, УТП), и использование подсистемы поможет тратить меньше времени на обновление таких конфигураций.

Эта подсистема – мой рабочий инструмент, которым я пользуюсь уже много лет и наконец-то решил поделиться им с сообществом.

Подсистема тестировалась на версии платформы 8.3.10.2667 и выше.

Кратко принцип работы подсистемы можно описать одной картинкой:

В типовую форму добавляются элементы формы-шаблона. Рассмотрим подробнее, как это реализовано.

Установка подсистемы

Вы можете добавить подсистему в свою конфигурацию сравнением/объединением.

В подсистему входят следующие объекты:

Еще необходимо в общем модуле обычного приложения прописать экспортную глобальную переменную:

Перем гл_ЮК_ПрограммныеФормы Экспорт;

В роли большой необходимости нет, главное – следите за тем, чтобы у всех пользователей были права на обработку ЮК_ПрограммныеФормы.

Добавление элементов на форму

В демобазе есть справочник "Товары". Представим, что это некий типовой справочник, в форму которого мы хотим внести изменения.

Изначально форма справочника выглядит вот так:

Предположим, мы хотим добавить новый реквизит справочника и новое поле "Страна-производитель". Чтобы быть уверенным, что новое поле не будет конфликтовать с элементами на форме, которые поставщик может добавить в будущем, сделаем это на новой вкладке "Мои свойства".

Для этого в обработке ЮК_ПрограммныеФормы добавим новую произвольную форму. Назвать ее можно как угодно, но практика показала, что в качестве имени удобно использовать полный путь к форме, для которой предназначен шаблон:

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

И добавить два реквизита формы произвольного типа: Форма и Объект (реквизит Объект для форм списков не обязателен).

В типовую форму, в событие "ПередОткрытием", добавим вызов процедуры:

ЮК_ПрограммныеФормы.ПередОткрытием("Справочники_Товары_ФормаЭлемента", ЭтаФорма, ЭтотОбъект, Отказ);

Первый параметр — имя формы шаблона. Затем передается типовая форма, объект и параметр отказа.

На этом подключение формы шаблона к типовой форме завершено.

Теперь внесем изменения.

Добавим на форму шаблона панель с таким же именем и таким же расположением, как и панель на типовой форме, назовем единственную страницу "МоиСвойства" и добавим надпись и поле "СтранаПроизводитель":

Теперь, перед открытием, на форму будет добавляться поле "СтранаПроизводитель". Для того, чтобы данные поля сохранялись, добавим в справочник реквизит шапки с таким же именем.

Если нужно изменить позицию новой вкладки, то в шаблоне, в тексте заголовка вкладки, нужно указать символ диез и номер позиции. Например:

Подсистема поддерживает НЕ ВСЕ визуальные элементы, которые могут быть размещены на форме. Информацию о том, какие типы визуальных элементов поддерживаются, можно получить из функции ЮК_ПрограммныеФормы.ПолучитьСвойстваИсключенияДляЭлемента.

Изначально подсистема создавалась именно для этих целей — добавлять новые вкладки на формы и произвольные поля с привязками на новых вкладках.

Но функционал подсистемы не ограничивается только этим.

Изменение существующих элементов

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

Давайте поменяем фон поля наименования.

Скопируем из типовой формы поле "Наименование" и разместим его в той же позиции на форме шаблона. А затем в свойствах поля поменяем цвет фона.

Обратите внимание, что вместе со свойствами элемента переносятся и его привязки. Если нужно отключить перенос привязок и оставить оригинальные привязки, которые установлены у элемента типовой формы, в подсказку элемента в шаблоне необходимо добавить ключевое слово #nolink:

События

Подсистема поддерживает трансляцию событий в шаблон.

Давайте попробуем это сделать. В шаблоне добавим полю "Наименование" кнопку открытия и создадим событие "Открытие".

Затем нужно сделать процедуру – обработчик события экспортной. И пропишем какой-то обработчик события.

После чего откроем форму в режиме предприятия. При открытии формы будет выдано сообщение о том, что не хватает обработчика события:

Скопируйте предложенные процедуры "как есть" и вставьте в модуль типовой формы.

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

Внимание! Для элемента типа "Табличное поле" (особенно в расширенных для дерева или справочника версиях) поддерживаются не все события. Получить перечень поддерживаемых событий можно из функции ЮК_ПрограммныеФормы.ПолучитьПолныйПереченьСобытийЭлемента.

Для самой формы транслируется ряд событий. В модуле шаблона можно объявить экспортные процедуры – обработчики событий:

  • ПередОткрытием
  • ПриОткрытии
  • ПередЗаписью
  • ПослеЗаписи
  • ПриЗакрытии

Для их трансляции в соответствующих событиях типовой формы необходимо прописать подобный код:

ЮК_ПрограммныеФормы.ПриЗакрытии("Справочники_Товары_ФормаЭлемента", ЭтаФорма, ЭтотОбъект);

Внимание! Если в типовой форме уже существовал обработчик соответствующего события формы и вы просто добавили вызов-трансляцию в существующую процедуру, то при обновлении нужно просто проследить за тем, чтобы вызов в коде не затерся. Однако если в типовой форме вы создавали обработчик события, то при обновлении может быть очищена связь процедуры – обработчика и события формы.

Контексты исполнения

Код, который выполняется в оттранслированных обработчиках событий, выполняется в контексте шаблона и может вызывать другие процедуры и функции модуля формы-шаблона. Однако в реквизитах формы-шаблона Объект и Форма находятся значения ЭтотОбъект и ЭтаФорма контекста типовой формы.

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

Формы списков и командные панели

Подсистема поддерживает изменение состава колонок табличных полей и добавление кнопок командных панелей.

Точно так же, как мы делали для формы элемента, сделаем шаблон для формы списка справочника Товары за одним исключением. Реквизит шаблона Объект добавлять не будем. И вызов перед открытием будет без объекта:

ЮК_ПрограммныеФормы.ПередОткрытием("Справочники_Товары_ФормаСписка", ЭтаФорма, , Отказ);

Для всех форм, где нет или не требуется объект, его можно не передавать.

Затем добавим табличное поле типа "ТаблицаЗначений" и командную панель. Имена добавленным элементам поставим такие же, как в типовой форме, тем самым сообщим подсистеме, что не нужно создавать новые элементы, а только модифицировать существующие.

И добавим в табличное поле колонку "СтранаПроизводитель", а в командную панель две кнопки и обработчики событий к ним (не забывая сделать их экспортными).

Как видите, при помощи символа диез в заголовках можно управлять позицией добавления кнопок и колонок. А что получилось в результате, вы можете посмотреть в демобазе.

Так как платформа не отрабатывает сохранение настроек позиции ширины и пр. для колонок табличного поля, добавленных программно, то для тех форм, где вы хотите, чтобы у пользователей сохранялись их настройки, по событию "ПриЗакрытии" необходимо вызывать функцию ЮК_ПрограммныеФормы.ПриЗакрытии. Обработчик события в форме-шаблоне добавлять не обязательно.

Для очистки таких сохраненных настроек в подсистеме есть обработка ЮК_ПрограммныеФормы_СохраненныеНастройкиКолонокТабличныхПолей.

Примечания и известные баги

Страницы формы

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

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

Форма "плывет"

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

Если он не помогает, то внимательно посмотрите расположение, привязки и размеры изменяемых и добавляемых элементов. Это может быть сложно, так как приходится "мыслить в трех измерениях". Добавьте #nolink всем элементам у которых нет необходимости переносить привязки из шаблона в типовую форму. Это помогает в 99% случаев. В моей практике была только одна ситуация, когда форма вела себя неадекватно и я так и не смог понять почему. Пришлось добавлять на нее элементы "старым дедовским способом".

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

В конечном итоге вы всегда можете написать автору подсистемы, но гарантий, что автор сможет помочь именно с вашим случаем, нет.

Ссылки

Про обнаруженные ошибки пишите на адрес me@zfilin.org.ua или в комментарии к публикации на Infostart.

Оригинал статьи в блоге автора

 

Спасибо за интерес к подсистеме, всем хорошего дня и хорошего кода.

10 Comments

  1. Darklight

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

    Хорошая альтернатива кодогенерации изменений интерфейса.

    У меня есть аналогичная разработка (ещё не закончена) — для управляемых форм — принцип практически тот же — разработка частей интерфейса в отдельной(ых) форме (фрейм) и их интеграция в финальную форму (программная realtime, или препроцессораная indesign)

    Reply
  2. zfilin

    (1) Заканчивайте скорее, а-то я тут уже раздумываю не начать ли писать свою такую же подсистему и для управляемых форм тоже. Но пока лень побеждает. =)

    Reply
  3. Darklight

    (2)А меня побеждает моя необузданная фантазия и десятки открытых и незаконченных проектов — между которыми я то и дело переключаюсь 🙁 + всё время новые идеи лезут 😉

    Reply
  4. zfilin

    (3)

    Reply
  5. k1rs

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

    Reply
  6. Darklight

    (5)У меня сейчас и так в работе 3 статьи

    Reply
  7. slawa

    для УФ уже есть с 16 года https://infostart.ru/public/547803/

    Reply
  8. zfilin

    Опубликована версия 1.0.0.3

    Изменения в версии:

    * мелкая доработка по табличному полю дереву

    Reply
  9. zfilin

    Опубликована версия 1.0.0.5

    Изменения в версии:

    * для существующих кнопок командной панели теперь можно переопределять действие

    * мелкие багфиксы

    Reply
  10. Vika260740

    Как человек, который часто использует данный функционал, могу сказать, что это очень удобно и круто! Автор молодец))

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *