Разработка интерфейсов в среде «1С:Предприятие 7.7» всегда сопровождалась определенными трудностями. Одной из наиболее частых проблем, с которой сталкиваются разработчики, является хаотичное поведение элементов управления (кнопок, текстовых полей, рамок) при изменении размеров формы пользователем. Кнопки, расположенные на одном слое и визуально находящиеся на одной линии, при растягивании окна могут внезапно «разлетаться» в разные стороны: одни остаются привязанными к верхнему краю, другие улетают вниз, а третьи и вовсе накладываются друг на друга.
В этой статье мы подробно разберем, как устроен штатный механизм изменения размеров диалогов в платформе 1С 7.7, почему возникает проблема «разбегающихся» кнопок и как ее можно элегантно решить как стандартными средствами конфигуратора, так и с помощью профессиональных инструментов — внешних компонент.
Рассмотрим все доступные варианты решения этой задачи по шагам.
Для начала проанализируем базовое поведение платформы. В отличие от современных версий (1С 8.x), в «семерке» нет полноценной объектной модели привязок (якорей или «anchors»). Вместо этого разработчикам доступен лишь один флаг в свойствах формы — «Изменяемый размер». Если этот флаг снят, окно формы жестко фиксируется в своих исходных размерах, и проблема масштабирования отпадает сама собой. Но если пользователям необходимо растягивать форму (например, чтобы видеть больше строк в табличной части), включается штатный геометрический алгоритм платформы.
Давайте выясним основные правила, по которым работает этот встроенный алгоритм:
ТабличнаяЧасть (для документов) или ТаблицаЗначений (для отчетов и обработок). Именно эта таблица объявляется главным масштабируемым объектом формы. При растягивании окна по ширине или высоте меняются геометрические размеры только этого элемента.Важное примечание: Порядок обхода элементов (клавиша Tab) также играет важную роль. Если на форме размещено несколько таблиц значений, то масштабироваться будет именно та, которая стоит первой в очереди обхода. Остальные таблицы будут позиционироваться по общим правилам обычных элементов.
Вернемся к вопросу автора темы: почему кнопки, добавленные на один слой в разное время, ведут себя по-разному? Разберем эту ситуацию подробнее.
Когда вы добавляете элементы управления на форму в разное время, вы можете случайно сдвинуть их координаты даже на один пиксель. Если одна кнопка хотя бы краем пересекает условную линию границы главной таблицы значений (или расположена чуть ниже ее верхней границы), а вторая кнопка находится строго выше этой границы, платформа отнесет их к разным группам позиционирования.
Ситуация сильно усложняется при использовании многослойных форм (закладки и слои). Физически элементы на скрытых слоях продолжают существовать в общей системе координат формы. Алгоритм платформы 1С 7.7 просчитывает взаимное расположение элементов на всех слоях одновременно, включая невидимые в данный момент. Если элемент на скрытом слое «наползает» на область таблицы, это ломает логику сдвига визуально независимых кнопок на активном слое. Кнопки начинают «разбегаться».
Чтобы исправить это стандартными средствами, выполните следующие действия в конфигураторе:
Верх) или горизонтали (свойство Лево).Если проектные ограничения не позволяют вам использовать внешние компоненты, разработчики часто прибегают к проверенным временем хитростям:
ТаблицуЗначений размером буквально 1х1 пиксель. Поместите ее в самый правый нижний угол формы. В свойствах элемента сделайте ее невидимой (убрав галочку «Видимость»). Сделайте эту ТЗ первой в порядке обхода. Теперь все кнопки на форме, расположенные левее и выше этой микро-таблицы, будут корректно сдвигаться вслед за ней к правому нижнему углу формы.HKEY_CURRENT_USER\Software\1C\1Cv7\7.7\<Имя_Базы>\V7\<Имя_Пользователя>\Windows.Для создания действительно качественного, отзывчивого и современного интерфейса в 1С 7.7 штатного функционала катастрофически не хватает. Опытные разработчики используют связку внешних компонент — FormEx.dll и 1cpp.dll.
Важное правило: Если вы планируете управлять привязками программно через код внешней компоненты, обязательно снимите галочку «Изменяемый размер» в свойствах формы в конфигураторе! Если ее оставить, штатный геометрический алгоритм платформы будет конфликтовать с вашим программным кодом, возвращая элементам прежние хаотичные координаты.
Давайте разберем по шагам, как настроить профессиональное масштабирование.
В стандартной платформе 1С 7.7 в процедуре ПриОткрытии() окно формы еще физически не создано в операционной системе, оно не имеет дескриптора окна (HWND). Из-за этого любые попытки изменить размеры элементов формы программно на данном этапе не увенчаются успехом.
Внешняя компонента FormEx решает эту проблему, добавляя в модуль формы предопределенную процедуру ПослеОткрытия(). В этой процедуре форма уже полностью отрисована, и мы можем безопасно управлять координатами любых элементов.
Для изменения координат конкретного элемента используется метод УстановитьКоординаты() объекта класса АтрибутФормы. Посмотрим на пример кода:
Процедура ПослеОткрытия()
// Создаем объект для управления атрибутом формы из библиотеки FormEx
АтрибутКнопки = СоздатьОбъект("АтрибутФормы");
АтрибутКнопки.УстановитьАтрибут(Форма, "кнОК");
// Получаем текущие координаты и принудительно задаем новые
// Параметры: Лево, Верх, Ширина, Высота
АтрибутКнопки.УстановитьКоординаты(100, 150, 80, 25);
КонецПроцедуры
Чтобы не прописывать вручную сложные математические формулы расчета координат для каждого элемента при каждом изменении размеров окна (событие `ПриИзмененииРазмераОкна`), в библиотеке классов 1С++ существует готовый класс привязок. Он позволяет декларативно привязать стороны любого элемента управления к сторонам формы или к другим элементам.
Сначала класс необходимо зарегистрировать в конфигурационном файле описания классов (обычно это файл defcls.prm в каталоге базы данных):
класс Общие.Форма.Привязка = Классы\Форма\Привязки\Общие.Форма.Привязка.ert{};
После регистрации класса мы можем легко инициализировать его прямо в модуле нашей формы. Давайте разберем практический пример привязки кнопки «ОК» к правому нижнему углу формы, а таблицы значений — по всей ширине и высоте окна.
В модуле формы пишем следующий код:
Переменная гРФорма; // Переменная для хранения объекта класса привязок
Процедура ПриОткрытии()
// Инициализируем класс привязок из библиотеки 1С++
гРФорма = СоздатьОбъект("Общие.Форма.Привязка");
гРФорма.УстановитьФорму(Форма);
// Настраиваем правила привязки для элементов формы.
// Параметры метода Привязка():
// 1. Идентификатор элемента формы.
// 2. К какому краю привязываем элемент (L - Лево, R - Право, T - Верх, B - Низ).
// 3. К какому объекту привязываем (обычно "Форма").
// Привязываем таблицу значений "ТЗ_Данные" так, чтобы она растягивалась
// во все стороны вместе с изменением размеров формы
гРФорма.Привязка("ТЗ_Данные", "R", "Форма", "R", "Форма");
гРФорма.Привязка("ТЗ_Данные", "B", "Форма", "B", "Форма");
// Привязываем кнопку "кнОК" к правому нижнему углу формы.
// Она не будет растягиваться, но будет смещаться вправо и вниз вслед за краем формы.
гРФорма.Привязка("кнОК", "L", "Форма", "R", "Форма");
гРФорма.Привязка("кнОК", "R", "Форма", "R", "Форма");
гРФорма.Привязка("кнОК", "T", "Форма", "B", "Форма");
гРФорма.Привязка("кнОК", "B", "Форма", "B", "Форма");
// Привязываем кнопку закрытия "кнЗакрыть" рядом с кнопкой ОК
гРФорма.Привязка("кнЗакрыть", "L", "Форма", "R", "Форма");
гРФорма.Привязка("кнЗакрыть", "R", "Форма", "R", "Форма");
гРФорма.Привязка("кнЗакрыть", "T", "Форма", "B", "Форма");
гРФорма.Привязка("кнЗакрыть", "B", "Форма", "B", "Форма");
КонецПроцедуры
Использование такого подхода гарантирует, что интерфейс вашей программы будет плавно и красиво масштабироваться под любые разрешения мониторов, включая современные широкоформатные экраны с высоким DPI, а кнопки больше никогда не будут хаотично разлетаться по форме.