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