При разработке сложных интерфейсов на платформе 1С:Предприятие 8.3 мы часто сталкиваемся с необходимостью программного формирования форм. Это мощный механизм, позволяющий создавать динамические интерфейсы, подстраивающиеся под роль пользователя или функциональные опции. Однако, иногда этот процесс сопровождается неприятными визуальными артефактами.
В этой статье мы подробно разберем ситуацию, когда программно добавленные элементы на управляемой форме компонуются с ошибкой: элементы "не влезают", обрезаются по ширине или накладываются друг на друга. Характерной чертой данной проблемы является то, что стоит пользователю хотя бы на один пиксель изменить размер окна (растянуть форму мышкой), как "глюк" исчезает, и форма перерисовывается корректно. Выясним причины такого поведения и рассмотрим проверенные методы решения.
Давайте проанализируем типичный сценарий возникновения ошибки. Разработчик в процедуре ПриСозданииНаСервере программно добавляет поля ввода, переключатели или декорации. При открытии формы в режиме Предприятия мы наблюдаем следующую картину:
Главный симптом, указывающий на природу ошибки: принудительная перерисовка интерфейса исправляет ситуацию. Это означает, что логическая структура формы верна, но механизм первичного расчета геометрии (layout engine) платформы ошибся в момент инициализации окна.
Основываясь на опыте сообщества разработчиков и анализе поведения платформы, выделим основные причины:
Перейдем к детальному рассмотрению методов решения этой проблемы, от наиболее правильных архитектурно до "боевых костылей", которые спасают в безвыходных ситуациях.
Как показала практика и обсуждение данной проблемы, "виновником" сбоя компоновки часто являются расширенные подсказки элементов. Даже если вы уменьшаете длину текста подсказки, она все равно может резервировать невидимое пространство в ячейке сетки формы, "распирая" или, наоборот, сжимая соседние элементы.
Эффективным решением является изоляция расширенных подсказок от основной сетки выравнивания формы. Рассмотрим, как это можно сделать.
Метод "Спрятать под шконку"
Суть метода заключается в том, чтобы программно привязать отображение расширенной подсказки к элементу, который не влияет на ширину полей ввода, либо вообще убрать её из потока верстки, если она не критична в данный момент.
Если подсказка создает "паразитный" отступ, попробуйте переместить её. В контексте обсуждаемой проблемы помогло перемещение расширенных подсказок в командную панель или в группу, которая не участвует в основном выравнивании колонок. Это освобождает движок отрисовки от необходимости рассчитывать сложные пересечения текстовых блоков подсказок и полей ввода.
Также проверьте свойство АвтоМаксимальнаяШирина у подсказок или декораций. Установка этого свойства в Ложь может запретить платформе бесконтрольно растягивать контейнер подсказки.
Если манипуляции с подсказками не помогают или они вам необходимы на своих местах, следующим шагом мы должны упорядочить структуру самой формы. Проблема часто возникает, когда элементы "валяются" в корне формы или в группах с автоматической группировкой.
Мы рекомендуем всегда оборачивать программно добавляемые элементы в группы с четко заданным поведением. Рассмотрим пример правильного создания структуры:
// Создаем группу для горизонтального размещения
НоваяГруппа = Элементы.Добавить("ГруппаНастроек", Тип("ГруппаФормы"), Элементы.ГлавнаяГруппа);
НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
НоваяГруппа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
// Важно: отключаем сквозное выравнивание, если элементы разъезжаются
НоваяГруппа.Отображение = ОтображениеОбычнойГруппы.Нет;
Использование свойства Группировка со значениями Горизонтальная или Вертикальная (вместо Авто) дает платформе жесткую инструкцию, как располагать элементы. Это минимизирует вероятность ошибки расчета ширины.
Также обратите внимание на свойство РастягиватьПоГоризонтали для самих элементов. Если переключатель обрезается, попробуйте явно разрешить или запретить ему растягивание, в зависимости от желаемого поведения.
В ситуациях, когда дизайн формы прост и не требует адаптивности под разные разрешения мониторов, можно прибегнуть к жесткой фиксации ширины. Это гарантированно решает проблему "дрожания" верстки, так как платформа сразу получает конечные размеры контейнера.
Вы можете задать ширину всей формы в свойствах или программно:
ЭтаФорма.Ширина = 60; // Примерное значение в символах
ЭтаФорма.ВариантУправленияВысотой = ВариантУправленияВысотойФормы.НавигационнаяПанель;
Однако, мы рекомендуем использовать этот метод с осторожностью. На мониторах с высоким DPI или нестандартным масштабированием шрифтов операционной системы жестко заданная ширина может привести к тому, что форма будет выглядеть слишком узкой или, наоборот, неоправданно широкой.
Если архитектурные решения не помогают (например, баг проявляется только на конкретной версии платформы или в Web-клиенте), существует способ программно эмулировать действие пользователя по изменению размера окна. Это заставляет платформу заново пересчитать координаты элементов.
Для реализации этого метода мы будем использовать подключение обработчика ожидания. Логика следующая: форма открывается, и через долю секунды срабатывает код, который "дергает" форму, заставляя её обновиться.
Рассмотрим пример реализации:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем однократный обработчик с минимальной задержкой
ПодключитьОбработчикОжидания("ОбновитьОтображениеФормы", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьОтображениеФормы()
// Вариант 1: Принудительное обновление
ЭтаФорма.ОбновитьОтображениеДанных();
// Вариант 2 (если первый не сработал): Микро-изменение размера или заголовка
// Иногда достаточно просто вызвать этот метод, чтобы запустить цикл отрисовки
// В крайних случаях меняют ширину на пиксель и обратно,
// но обычно ОбновитьОтображениеДанных() или чтение свойств элементов достаточно.
КонецПроцедуры
Этот метод часто называют "костылем", но в условиях реальной эксплуатации, когда обновить платформу у всех пользователей невозможно, он является спасением.
Подводя итог, давайте перечислим еще несколько настроек, которые могут влиять на корректность компоновки:
ВертикальнаяПрокрутка в значение ИспользоватьПриНеобходимости. Иногда наличие или отсутствие скроллбара влияет на расчет внутренней ширины рабочей области.ПоложениеЗаголовка. Например, установка значения Нет или Слева может изменить алгоритм расчета ширины контрола.Мы проанализировали основные способы борьбы с ошибками компоновки в управляемых формах. Начинайте с проверки расширенных подсказок и группировок — это наиболее "чистые" методы решения. И только если они не помогают, используйте программную фиксацию размеров или принудительное обновление отображения.