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