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