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