К статье
Практический материал

Разработка и Конфигурация · 11 мин

Модальный диалог в 1С: как закрыть

Как закрыть модальный диалог в 1С: метод Закрыть(), команды формы, обработчики ПередЗакрытием, блокирующие окна и решение проблем с зависшими диалогами.

Модальный диалог в 1С — это окно, которое блокирует работу с остальным интерфейсом, пока пользователь не ответит на вопрос или не закроет форму. Такие окна используются для подтверждений, вопросов, выбора значений и вывода критических предупреждений. Закрыть их можно как со стороны пользователя (кнопки, клавиша Esc), так и программно — методами встроенного языка.

Проблемы возникают в двух ситуациях: когда разработчику нужно закрыть форму из кода, а стандартный вызов не срабатывает, и когда пользователь сталкивается с «зависшим» диалогом, который не реагирует на нажатия. В обоих случаях причина обычно кроется в логике обработчиков закрытия или в режиме открытия окна.

Ниже разобраны способы закрытия модальных и блокирующих окон в управляемом и обычном приложении, типовые ошибки при программном закрытии и действия при зависшем диалоге.

Чем модальное окно отличается от блокирующего

В платформе 1С есть два близких режима: модальное окно и окно, блокирующее весь интерфейс или окно-владельца. Модальная форма открывается устаревшим методом ОткрытьМодально() и полностью останавливает выполнение кода до закрытия. Блокирующая форма открывается через ОткрытьФорму() с параметром РежимОткрытияОкна и не останавливает выполнение кода — результат возвращается через оповещение.

Разница важна для выбора способа закрытия. Модальная форма, открытая через ОткрытьМодально(), возвращает значение напрямую в точку вызова. Блокирующая форма передаёт результат через ОписаниеОповещения, которое обрабатывается после её закрытия. Современные конфигурации на управляемых формах используют именно второй вариант, потому что модальный режим не поддерживается в веб-клиенте и мобильной платформе.

Как закрыть форму программно: метод Закрыть()

Основной способ — вызов метода Закрыть() в контексте формы. В модуле формы достаточно написать Закрыть();, и форма завершит работу. Если форма открыта для выбора или вопроса, в метод передают возвращаемое значение: Закрыть(ВыбранноеЗначение);.

Типовой пример — обработка команды «ОК» в диалоге подтверждения:

&НаКлиенте

Процедура КомандаОК(Команда)

Закрыть(Истина);

КонецПроцедуры

&НаКлиенте

Процедура КомандаОтмена(Команда)

Закрыть(Неопределено);

КонецПроцедуры

Чтобы закрыть форму из другого места программы, сначала получают на неё ссылку — через ПолучитьФорму() или через сохранённую переменную, — а затем вызывают Форма.Закрыть();. Если форма уже закрыта, повторный вызов метода безопасен и не вызывает ошибки, но проверка Форма.Открыта() делает код надёжнее.

bsl
Если ФормаДиалога <> Неопределено И ФормаДиалога.Открыта() Тогда
    ФормаДиалога.Закрыть();
КонецЕсли;

Закрытие вопроса и предупреждения, открытых системными методами

Диалоги, открытые через ПоказатьВопрос() и ПоказатьПредупреждение(), закрываются самим пользователем — кнопками «Да», «Нет», «ОК» и тому подобными. Программно закрыть такой системный диалог из кода нельзя: у него нет доступного объекта формы.

Если требуется диалог, который закрывается по таймеру или извне, системные методы не подходят. Вместо них создают собственную форму с нужными кнопками, открывают её с блокировкой интерфейса и закрывают методом Закрыть() в нужный момент — например, по обработчику ожидания через ПодключитьОбработчикОжидания().

Устаревшие методы Вопрос() и Предупреждение() работают в модальном режиме и также не имеют программного закрытия. В новых разработках их не применяют: они несовместимы с веб-клиентом и тонким клиентом без модальности.

Почему форма не закрывается: обработчик ПередЗакрытием

Частая причина «неработающего» метода Закрыть() — обработчик события ПередЗакрытием в модуле формы. Если в нём установлено Отказ = Истина, закрытие отменяется независимо от того, кто его инициировал — пользователь или код.

Типовой сценарий — защита от потери данных: в обработчике проверяют Модифицированность и задают вопрос о сохранении. Пока пользователь не ответит, форма остаётся открытой. Чтобы программно закрыть такую форму без вопросов, в коде перед закрытием сбрасывают признак модифицированности или устанавливают служебный флаг, который обработчик учитывает:

&НаКлиенте

Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)

Если ПринудительноеЗакрытие Тогда

Возврат;

КонецЕсли;

Если Модифицированность Тогда

Отказ = Истина;

// вопрос о сохранении

КонецЕсли;

КонецПроцедуры

Дополнительные причины отказа: ошибка в обработчике ПриЗакрытии, обращение к уже удалённым данным формы, попытка закрыть форму из серверного контекста, где метод недоступен. Метод Закрыть() работает только на клиенте — вызов с директивой &НаСервере приведёт к ошибке компиляции или выполнения.

Типичные ошибки
01
Вызов Закрыть() в серверной процедуре — метод доступен только на клиенте, код падает с ошибкой
02
Игнорирование Отказ = Истина в ПередЗакрытием — форма «не реагирует» на программное закрытие
03
Использование ОткрытьМодально() в конфигурации для веб-клиента — окно не открывается или работает некорректно
04
Закрытие формы до завершения фоновой операции, которая пишет в её реквизиты — обращение к закрытой форме вызывает ошибку

Как пользователю закрыть зависший или неудобный диалог

С точки зрения пользователя модальный диалог закрывается штатными способами: нажатием одной из кнопок диалога, крестиком в заголовке окна, клавишей Esc (если разработчик не отключил стандартную обработку). В большинстве форм выбора и вопросов Esc эквивалентна отказу или отмене.

Если диалог не реагирует — программа, скорее всего, выполняет длительную операцию, и интерфейс временно заблокирован. Стоит подождать: принудительное завершение сеанса во время записи данных может привести к незавершённым транзакциям. Если окно зависло окончательно, сеанс завершают через диспетчер задач (для толстого и тонкого клиента) или закрытием вкладки браузера (для веб-клиента), а в клиент-серверном варианте администратор может завершить сеанс из консоли кластера.

Отдельный случай — модальное окно, скрывшееся за главным окном программы. Интерфейс при этом кажется «зависшим»: клики по основному окну не работают. Помогает переключение между окнами через Alt+Tab — скрытый диалог выводится на передний план и закрывается обычным способом.

Открытие формы с блокировкой и получение результата после закрытия

Правильный современный шаблон диалога выглядит так: форма открывается с блокировкой владельца, а результат обрабатывается в оповещении после закрытия. Это заменяет модальный вызов и работает во всех клиентах.

&НаКлиенте

Процедура ВыбратьДействие(Команда)

Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияДиалога", ЭтотОбъект);

ОткрытьФорму("Обработка.МояОбработка.Форма.ДиалогВыбора", , ЭтотОбъект, , , ,

Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

КонецПроцедуры

&НаКлиенте

Процедура ПослеЗакрытияДиалога(Результат, ДопПараметры) Экспорт

Если Результат = Неопределено Тогда

Возврат; // пользователь нажал Отмену или Esc

КонецЕсли;

// обработка результата

КонецПроцедуры

Обратите внимание на проверку результата на Неопределено: если пользователь закрыл форму крестиком или Esc, метод Закрыть() с параметром не вызывался, и в оповещение приходит пустое значение. Обработка этого случая обязательна, иначе логика продолжит работу с несуществующим выбором.

Порядок действий при незакрывающейся форме
  1. 1
    Откройте модуль формы и найдите обработчик ПередЗакрытием
  2. 2
    Проверьте, нет ли в нём условия с Отказ = Истина и не срабатывает ли оно
  3. 3
    Убедитесь, что Закрыть() вызывается в клиентской процедуре, а не на сервере
  4. 4
    Проверьте, что форма ещё открыта: Форма.Открыта() возвращает Истина
  5. 5
    Запустите отладку и убедитесь, что вызов Закрыть() вообще выполняется
  6. 6
    После исправления проверьте закрытие всеми способами: кнопкой, крестиком, Esc и из кода

Проверка результата и контрольные точки

После внедрения или исправления логики закрытия проверяют все пути выхода из диалога: штатные кнопки, крестик, Esc, программный вызов. Каждый путь должен либо возвращать осмысленный результат, либо явно трактоваться как отмена.

Дополнительно проверяют поведение при повторном открытии: форма не должна сохранять устаревшее состояние, а вызывающий код — обращаться к закрытой форме. Если после закрытия в журнале регистрации появляются ошибки «объект не найден» или «форма закрыта», значит, где-то осталось обращение к реквизитам формы после её уничтожения.

Контрольные точки

Как проверить результат

Закрытие кнопкой ОК
Норма

Оповещение получает переданное значение, форма исчезает

Тревожный признак

Оповещение не срабатывает или приходит Неопределено

Закрытие через Esc или крестик
Норма

Вызывающий код корректно обрабатывает отмену

Тревожный признак

Логика продолжается, как будто выбор сделан

Программный вызов Закрыть()
Норма

Форма закрывается без ошибок в журнале

Тревожный признак

Отказ в ПередЗакрытием или ошибка в ПриЗакрытии

Повторное открытие диалога
Норма

Форма открывается в исходном состоянии

Тревожный признак

Остаточные данные прошлого сеанса работы формы

Ответы на частые вопросы

Как закрыть все открытые формы в 1С программно?

Единого метода «закрыть всё» нет. Нужно хранить ссылки на открытые формы (например, в массиве или через оповещения) и вызывать Закрыть() для каждой. Окна самостоятельных объектов можно найти через Оповестить() с событием, на которое формы подписаны обработчиком, закрывающим их.

Почему Закрыть() не работает в веб-клиенте?

Сам метод работает, но часто проблема в том, что форма открыта устаревшим ОткрытьМодально(), который в веб-клиенте не поддерживается. Переведите открытие на ОткрытьФорму() с описанием оповещения и режимом БлокироватьОкноВладельца.

Можно ли запретить закрытие диалога по Esc и крестику?

Да, в обработчике ПередЗакрытием установите Отказ = Истина при нежелательном способе закрытия, оставив штатные кнопки. Полностью блокировать закрытие не рекомендуется — пользователь должен иметь понятный путь выхода из диалога.

Что вернёт оповещение, если пользователь просто закрыл окно?

Значение Неопределено. Поэтому в обработчике оповещения первым делом проверяют результат на Неопределено и трактуют его как отмену операции.

Как закрыть диалог автоматически через заданное время?

Создайте собственную форму диалога, при открытии подключите обработчик ожидания через ПодключитьОбработчикОжидания("ЗакрытьПоТаймеру", 10, Истина), а в указанной процедуре вызовите Закрыть(). Системные ПоказатьВопрос() и ПоказатьПредупреждение() такой возможности не дают.

Окно диалога скрылось, и программа «зависла» — что делать?

Нажмите Alt+Tab и найдите скрытое модальное окно среди открытых окон. После его закрытия интерфейс разблокируется. Если окна нет, а блокировка осталась, вероятно, выполняется длительная операция — дождитесь её завершения.

Итог

Что важно запомнить

Программное закрытие выполняется методом Закрыть() на клиенте, результат передаётся параметром и принимается через описание оповещения. Если форма не закрывается, ищите Отказ = Истина в ПередЗакрытием. Системные диалоги из кода не закрываются — для управляемых сценариев создают собственную форму.