Модальные и блокирующие окна в 1С 8.3: как они работают и почему их запрещают

· 9 мин

Содержание

Модальное окно в 1С 8.3 — это окно, которое останавливает выполнение кода до тех пор, пока пользователь его не закроет: Вопрос(), Предупреждение(), ОткрытьФормуМодально(). В новых конфигурациях такие вызовы запрещены свойством Режим использования модальности, а вместо них применяют асинхронные методы — ПоказатьВопрос(), ОткрытьФорму() с описанием оповещения или Ждать ВопросАсинх().

Типичная ситуация: бухгалтер запускает старую внешнюю обработку в свежей Бухгалтерии 3.0 и получает сообщение Использование модальных окон в данном режиме запрещено!. Обработка работала годами, база обновилась — и всё. Причина не в базе и не в правах, а в том, как написан код обработки. Разберём, как устроена модальность, где её включают и как переписать вызовы.

Суть модального окна и чем оно отличается от обычного диалога

Слово «модальное» в 1С используют в двух смыслах, и из-за этого часто путаются.

🔒 Модальное окно (в смысле платформы) — вызов, который «замораживает» процедуру. Код дошёл до строки Ответ = Вопрос(...), показал окно и ждёт. Следующая строка выполнится только после нажатия кнопки, а в переменной Ответ окажется результат.

🪟 Блокирующее окно — окно, которое закрывает пользователю доступ к другим окнам, но код не останавливает. Процедура, открывшая такое окно, выполняется дальше и завершается. Результат приходит позже — в отдельную процедуру-обработчик.

Внешне пользователь разницы не видит: и там и там поверх формы висит окно, мимо которого не кликнуть. Разница только в коде.

ПризнакМодальное окноБлокирующее окно
Код после вызоваЖдёт закрытия окнаВыполняется сразу
Как получить результатВозвращаемое значение методаПроцедура из ОписаниеОповещения
Пример методовВопрос(), ВвестиЧисло(), ОткрытьМодально()ПоказатьВопрос(), ПоказатьВводЧисла(), ОткрытьФорму()
Веб-клиент и мобильный клиентПроблемы с всплывающими окнами браузера, на мобильных не работаетРаботает везде
Запрет режимом модальностиДаНет

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

Зачем фирма 1С ушла от модальности

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

Поэтому с версии платформы 8.3.3 появилась возможность отказаться от модальности, а типовые конфигурации переписали на асинхронную модель.

Виды блокирующих и модальных окон в интерфейсе «Такси»

В «Такси» формы по умолчанию открываются в рабочей области основного окна, как вкладки. Отдельным окном поверх интерфейса показываются только те формы, которые что-то блокируют.

Режим открытия формы задаёт свойство РежимОткрытияОкна. У него три значения:

  1. Независимый — обычная форма. Открывается вкладкой, ничего не блокирует. Так открываются документы и справочники.
  2. БлокироватьОкноВладельца — блокирует только форму-владельца. Например, форма подбора блокирует документ, из которого её вызвали, но другие вкладки доступны.
  3. БлокироватьВесьИнтерфейс — блокирует всё приложение. Пользователь ничего не сделает, пока не закроет окно.

Кроме форм конфигурации, блокирующими бывают системные диалоги:

  • ❓ вопрос с кнопками «Да/Нет», «ОК/Отмена» — ПоказатьВопрос();
  • ⚠️ предупреждение с одной кнопкой — ПоказатьПредупреждение();
  • 🔢 ввод числа, строки, даты — ПоказатьВводЧисла(), ПоказатьВводСтроки(), ПоказатьВводДаты();
  • 📋 выбор значения из списка — метод ПоказатьВыборЭлемента() у списка значений;
  • 📁 выбор файла — ДиалогВыбораФайла.Показать().

Все они блокируют весь интерфейс, но ход кода не останавливают.

Режим БлокироватьВесьИнтерфейс не злоупотребляйте. Пользователь не сможет даже переключиться на соседний документ, чтобы подсмотреть сумму. Для подбора и выбора из списка обычно хватает БлокироватьОкноВладельца.

Режим использования модальности в Конфигураторе

Главная настройка находится в свойствах корня конфигурации. Откройте Конфигуратор, в дереве конфигурации щёлкните правой кнопкой по самому верхнему элементу и выберите Свойства. В палитре свойств найдите группу «Совместимость» и свойство Режим использования модальности.

Значения такие:

ЗначениеЧто происходит при модальном вызовеКогда выбирать
Не использоватьОшибка выполнения, окно не открываетсяНовые конфигурации, работа через веб и мобильный клиент
Использовать с предупреждениямиОкно открывается, в окно сообщений при отладке выводится предупреждениеПереходный период, пока код переписывают
ИспользоватьМодальные вызовы работают как раньшеСтарые самописные конфигурации, только тонкий клиент

У новой конфигурации по умолчанию стоит «Не использовать». У конфигураций, созданных на старых платформах и обновлённых, часто остаётся «Использовать».

Рядом в той же группе есть второе похожее свойство — Режим использования синхронных вызовов расширений платформы и внешних компонент. Оно касается работы с файлами, буфером и внешними компонентами. Логика та же: синхронные методы вроде ДиалогВыбораФайла.Выбрать() заменяют асинхронными.

Можно ли включить модальность в типовой конфигурации

Технически да, но это плохая идея.

  • 🛑 Типовая конфигурация на поддержке не даст изменить свойство корня, пока не включена возможность изменения. После этого обновления пойдут через сравнение и объединение, а это постоянная ручная работа.
  • 🛑 Типовой код уже асинхронный. Включение модальности ничего в нём не улучшит, а только разрешит старые внешние обработки.
  • 🛑 Веб-клиент и сервис «1С:Фреш» с модальными окнами работать нормально не будут.

Правильный путь — переписать внешнюю обработку, а не менять свойства типовой конфигурации.

Как найти все модальные вызовы

В Конфигураторе запустите Конфигурация → Проверка конфигурации и отметьте флажок поиска использования модальности. Проверка выведет список строк кода, где вызываются модальные методы.

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

Программный вызов: старый синтаксис и новые методы

Ниже — одна и та же задача тремя способами: спросить «Удалить строки?» и удалить при ответе «Да».

Модальный вызов (так писали до 8.3.3)

&НаКлиенте
Процедура УдалитьСтроки(Команда)
    Ответ = Вопрос("Удалить выбранные строки?", РежимДиалогаВопрос.ДаНет);
    Если Ответ = КодВозвратаДиалога.Да Тогда
        УдалитьСтрокиНаСервере();
    КонецЕсли;
КонецПроцедуры

При режиме «Не использовать» на строке с Вопрос() будет ошибка.

Описание оповещения (работает с 8.3.3)

&НаКлиенте
Процедура УдалитьСтроки(Команда)
    Оповещение = Новый ОписаниеОповещения("УдалитьСтрокиЗавершение", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, "Удалить выбранные строки?",
        РежимДиалогаВопрос.ДаНет, 0, КодВозвратаДиалога.Нет);
КонецПроцедуры

&НаКлиенте
Процедура УдалитьСтрокиЗавершение(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        УдалитьСтрокиНаСервере();
    КонецЕсли;
КонецПроцедуры

Что здесь важно:

  1. Процедура-обработчик обязана быть экспортной и лежать в модуле, который указан вторым параметром (ЭтотОбъект — модуль формы).
  2. Параметры ПоказатьВопрос() по порядку: оповещение, текст, кнопки, таймаут в секундах (0 — без таймаута), кнопка по умолчанию.
  3. Всё, что раньше шло после Вопрос(), переезжает в обработчик. Код после ПоказатьВопрос() в первой процедуре выполнится сразу, не дожидаясь ответа.

Если обработчику нужны данные из первой процедуры, передайте их третьим параметром конструктора ОписаниеОповещения — они придут в ДополнительныеПараметры.

Асинх и Ждать (платформа 8.3.18 и новее)

&НаКлиенте
Асинх Процедура УдалитьСтроки(Команда)
    Ответ = Ждать ВопросАсинх("Удалить выбранные строки?", РежимДиалогаВопрос.ДаНет);
    Если Ответ = КодВозвратаДиалога.Да Тогда
        УдалитьСтрокиНаСервере();
    КонецЕсли;
КонецПроцедуры

Код читается почти как старый модальный, но модальности тут нет: процедура помечена Асинх, а Ждать приостанавливает только её, не блокируя клиент. Аналогично работают ПредупреждениеАсинх(), ВвестиЧислоАсинх(), ВвестиСтрокуАсинх(), ВвестиДатуАсинх().

Ждать можно писать только внутри процедуры или функции с пометкой Асинх. И проверьте режим совместимости конфигурации: если он ниже 8.3.18, ключевые слова не будут доступны.

Открытие своей формы с ожиданием результата

Старый вариант — ОткрытьФормуМодально() или метод формы ОткрытьМодально(). Новый — ОткрытьФорму():

&НаКлиенте
Процедура ВыбратьПериод(Команда)
    Оповещение = Новый ОписаниеОповещения("ВыбратьПериодЗавершение", ЭтотОбъект);
    ОткрытьФорму("Обработка.МояОбработка.Форма.ВыборПериода", , ЭтаФорма, , , ,
        Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьПериодЗавершение(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = Неопределено Тогда
        Возврат; // пользователь закрыл форму крестиком
    КонецЕсли;
    Период = Результат;
КонецПроцедуры

В вызываемой форме результат возвращают так: Закрыть(ВыбранныйПериод). Значение из Закрыть() и попадёт в параметр Результат обработчика.

Таблица замен для быстрого перевода кода

Модальный методЗамена с оповещениемЗамена с Асинх
Вопрос()ПоказатьВопрос()Ждать ВопросАсинх()
Предупреждение()ПоказатьПредупреждение()Ждать ПредупреждениеАсинх()
ВвестиЧисло()ПоказатьВводЧисла()Ждать ВвестиЧислоАсинх()
ВвестиСтроку()ПоказатьВводСтроки()Ждать ВвестиСтрокуАсинх()
ВвестиДату()ПоказатьВводДаты()Ждать ВвестиДатуАсинх()
ОткрытьФормуМодально()ОткрытьФорму() с оповещением о закрытии—

Последний столбец пригодится, если у вас много коротких вопросов в одной процедуре: с Асинх они остаются в одном месте, без разбиения на обработчики.

Блокировка интерфейса, зависания и ошибка запрета модальности

Диагностика: выберите симптом

Почему окно «зависает» за основным

В «Такси» блокирующая форма — отдельное окно операционной системы. Если пользователь в этот момент переключился в браузер или почту, то при возврате Windows может вывести на передний план основное окно 1С, а не блокирующее. Интерфейс выглядит мёртвым, хотя 1С просто ждёт ответа.

Такое часто принимают за зависание и снимают процесс через диспетчер задач. Не завершайте процесс 1cv8c.exe, пока не проверили Alt+Tab: несохранённые данные в открытых формах пропадут.

Вызовы с сервера

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

Хорошие практики при работе с окнами в разработке

  1. Не используйте модальные методы в новом коде даже там, где их разрешает режим. Конфигурацию рано или поздно откроют через веб-клиент.
  2. Задавайте кнопку по умолчанию осторожно. Для опасных действий («Удалить», «Провести с перезаписью») по умолчанию ставьте «Нет»: пользователь, нажавший Enter по привычке, ничего не сломает.
  3. Таймаут — только для неважных вопросов. Если окно закрывается само через 30 секунд, решите, какой ответ будет считаться выбранным, и укажите его параметром кнопки таймаута.
  4. Проверяйте Неопределено в обработчике. Форму могут закрыть крестиком или клавишей Esc, и результат будет пустым.
  5. Не вкладывайте вопросы друг в друга бесконечно. Цепочка из трёх-четырёх ПоказатьВопрос() с обработчиками быстро становится нечитаемой. Если платформа позволяет — переходите на Асинх/Ждать, а для сложного сценария делайте одну форму с несколькими полями.
  6. Выбирайте минимальный уровень блокировки. БлокироватьОкноВладельца почти всегда удобнее пользователю, чем блокировка всего интерфейса.
  7. Внешние обработки для чужих баз пишите сразу асинхронно. Обработка с модальными вызовами откроется не у всех клиентов, а с асинхронными — у всех.
Перед передачей обработки заказчику
Выполнено: 0 / 5

Частые вопросы

С какой версии платформы появилась настройка режима модальности?
Свойство Режим использования модальности появилось в платформе 8.3.3. Ключевые слова Асинх и Ждать — в 8.3.18.
Влияет ли режим модальности на внешние обработки?
Да. Внешняя обработка выполняется в контексте базы и подчиняется её настройке. Если в конфигурации стоит «Не использовать», модальные вызовы обработки вызовут ошибку.
Можно ли сделать окно, которое не даёт работать с остальной программой, без модальности?
Можно. Откройте форму через ОткрытьФорму() с режимом РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс. Пользователь не сможет переключиться, но код не будет остановлен.
Работает ли модальность в обычных формах и толстом клиенте?
В обычном приложении модальные вызовы традиционно используются, и старые конфигурации на обычных формах обычно держат режим «Использовать». Запрет актуален прежде всего для управляемого приложения.
Что выбрать для перехода: оповещения или Асинх?
Если режим совместимости конфигурации 8.3.18 или новее — Асинх/Ждать, код короче и проще. Если конфигурация должна работать на старых платформах — ОписаниеОповещения.