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