Модальные и блокирующие окна в 1С 8.3: как они работают и почему их запрещают
Содержание
Модальное окно в 1С 8.3 — это окно, которое останавливает выполнение кода до тех пор, пока пользователь его не закроет: Вопрос(), Предупреждение(), ОткрытьФормуМодально(). В новых конфигурациях такие вызовы запрещены свойством Режим использования модальности, а вместо них применяют асинхронные методы — ПоказатьВопрос(), ОткрытьФорму() с описанием оповещения или Ждать ВопросАсинх().
Типичная ситуация: бухгалтер запускает старую внешнюю обработку
в свежей Бухгалтерии 3.0 и получает сообщение Использование модальных окон в данном режиме запрещено!. Обработка работала годами, база обновилась — и всё. Причина не в базе и не в правах, а в том, как написан код обработки. Разберём, как устроена модальность, где её включают и как переписать вызовы.
Суть модального окна и чем оно отличается от обычного диалога
Слово «модальное» в 1С используют в двух смыслах, и из-за этого часто путаются.
🔒 Модальное окно (в смысле платформы) — вызов, который «замораживает» процедуру. Код дошёл до строки Ответ = Вопрос(...), показал окно и ждёт. Следующая строка выполнится только после нажатия кнопки, а в переменной Ответ окажется результат.
🪟 Блокирующее окно — окно, которое закрывает пользователю доступ к другим окнам, но код не останавливает. Процедура, открывшая такое окно, выполняется дальше и завершается. Результат приходит позже — в отдельную процедуру-обработчик.
Внешне пользователь разницы не видит: и там и там поверх формы висит окно, мимо которого не кликнуть. Разница только в коде.
| Признак | Модальное окно | Блокирующее окно |
|---|---|---|
| Код после вызова | Ждёт закрытия окна | Выполняется сразу |
| Как получить результат | Возвращаемое значение метода | Процедура из ОписаниеОповещения |
| Пример методов | Вопрос(), ВвестиЧисло(), ОткрытьМодально() | ПоказатьВопрос(), ПоказатьВводЧисла(), ОткрытьФорму() |
| Веб-клиент и мобильный клиент | Проблемы с всплывающими окнами браузера, на мобильных не работает | Работает везде |
| Запрет режимом модальности | Да | Нет |
Если в задании от заказчика написано «сделать модальное окно», почти всегда имеется в виду блокирующее. Сделать окно, мимо которого нельзя кликнуть, можно и без модальных вызовов.
Зачем фирма 1С ушла от модальности
Модальный вызов держит поток выполнения на клиенте. В тонком клиенте под Windows это работает, а в браузере — нет: браузеры не умеют синхронно ждать ответа из всплывающего окна и часто блокируют такие окна. Мобильные платформы модальные окна вообще не поддерживают.
Поэтому с версии платформы 8.3.3 появилась возможность отказаться от модальности, а типовые конфигурации переписали на асинхронную модель.
Виды блокирующих и модальных окон в интерфейсе «Такси»
В «Такси» формы по умолчанию открываются в рабочей области основного окна, как вкладки. Отдельным окном поверх интерфейса показываются только те формы, которые что-то блокируют.
Режим открытия формы задаёт свойство РежимОткрытияОкна. У него три значения:
Независимый— обычная форма. Открывается вкладкой, ничего не блокирует. Так открываются документы и справочники.БлокироватьОкноВладельца— блокирует только форму-владельца. Например, форма подбора блокирует документ, из которого её вызвали, но другие вкладки доступны.БлокироватьВесьИнтерфейс— блокирует всё приложение. Пользователь ничего не сделает, пока не закроет окно.
Кроме форм конфигурации, блокирующими бывают системные диалоги:
- ❓ вопрос с кнопками «Да/Нет», «ОК/Отмена» —
ПоказатьВопрос(); - ⚠️ предупреждение с одной кнопкой —
ПоказатьПредупреждение(); - 🔢 ввод числа, строки, даты —
ПоказатьВводЧисла(),ПоказатьВводСтроки(),ПоказатьВводДаты(); - 📋 выбор значения из списка — метод
ПоказатьВыборЭлемента()у списка значений; - 📁 выбор файла —
ДиалогВыбораФайла.Показать().
Все они блокируют весь интерфейс, но ход кода не останавливают.
Режим БлокироватьВесьИнтерфейс не злоупотребляйте. Пользователь не сможет даже переключиться на соседний документ, чтобы подсмотреть сумму. Для подбора и выбора из списка обычно хватает БлокироватьОкноВладельца.
Режим использования модальности в Конфигураторе
Главная настройка находится в свойствах корня конфигурации. Откройте Конфигуратор, в дереве конфигурации щёлкните правой кнопкой по самому верхнему элементу и выберите Свойства. В палитре свойств найдите группу «Совместимость» и свойство Режим использования модальности.
Значения такие:
| Значение | Что происходит при модальном вызове | Когда выбирать |
|---|---|---|
| Не использовать | Ошибка выполнения, окно не открывается | Новые конфигурации, работа через веб и мобильный клиент |
| Использовать с предупреждениями | Окно открывается, в окно сообщений при отладке выводится предупреждение | Переходный период, пока код переписывают |
| Использовать | Модальные вызовы работают как раньше | Старые самописные конфигурации, только тонкий клиент |
У новой конфигурации по умолчанию стоит «Не использовать». У конфигураций, созданных на старых платформах и обновлённых, часто остаётся «Использовать».
Рядом в той же группе есть второе похожее свойство — Режим использования синхронных вызовов расширений платформы и внешних компонент. Оно касается работы с файлами, буфером и внешними компонентами. Логика та же: синхронные методы вроде ДиалогВыбораФайла.Выбрать() заменяют асинхронными.
Можно ли включить модальность в типовой конфигурации
Технически да, но это плохая идея.
- 🛑 Типовая конфигурация на поддержке не даст изменить свойство корня, пока не включена возможность изменения. После этого обновления пойдут через сравнение и объединение, а это постоянная ручная работа.
- 🛑 Типовой код уже асинхронный. Включение модальности ничего в нём не улучшит, а только разрешит старые внешние обработки.
- 🛑 Веб-клиент и сервис «1С:Фреш» с модальными окнами работать нормально не будут.
Правильный путь — переписать внешнюю обработку, а не менять свойства типовой конфигурации.
Как найти все модальные вызовы
В Конфигураторе запустите Конфигурация → Проверка конфигурации и отметьте флажок поиска использования модальности. Проверка выведет список строк кода, где вызываются модальные методы.
Для одного модуля удобнее рефакторинг: в контекстном меню текста модуля есть группа Рефакторинг, в ней — команды поиска и преобразования модальных (в новых платформах — «нерекомендуемых синхронных») вызовов. Автоматическое преобразование создаёт процедуру-обработчик и описание оповещения. Код после него нужно перечитать: сложные ветки с циклами конвертер переносит не всегда аккуратно.
Программный вызов: старый синтаксис и новые методы
Ниже — одна и та же задача тремя способами: спросить «Удалить строки?» и удалить при ответе «Да».
Модальный вызов (так писали до 8.3.3)
&НаКлиенте
Процедура УдалитьСтроки(Команда)
Ответ = Вопрос("Удалить выбранные строки?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
УдалитьСтрокиНаСервере();
КонецЕсли;
КонецПроцедуры
При режиме «Не использовать» на строке с Вопрос() будет ошибка.
Описание оповещения (работает с 8.3.3)
&НаКлиенте
Процедура УдалитьСтроки(Команда)
Оповещение = Новый ОписаниеОповещения("УдалитьСтрокиЗавершение", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Удалить выбранные строки?",
РежимДиалогаВопрос.ДаНет, 0, КодВозвратаДиалога.Нет);
КонецПроцедуры
&НаКлиенте
Процедура УдалитьСтрокиЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
УдалитьСтрокиНаСервере();
КонецЕсли;
КонецПроцедуры
Что здесь важно:
- Процедура-обработчик обязана быть экспортной и лежать в модуле, который указан вторым параметром (
ЭтотОбъект— модуль формы). - Параметры
ПоказатьВопрос()по порядку: оповещение, текст, кнопки, таймаут в секундах (0 — без таймаута), кнопка по умолчанию. - Всё, что раньше шло после
Вопрос(), переезжает в обработчик. Код послеПоказатьВопрос()в первой процедуре выполнится сразу, не дожидаясь ответа.
Если обработчику нужны данные из первой процедуры, передайте их третьим параметром конструктора ОписаниеОповещения — они придут в ДополнительныеПараметры.
Асинх и Ждать (платформа 8.3.18 и новее)
&НаКлиенте
Асинх Процедура УдалитьСтроки(Команда)
Ответ = Ждать ВопросАсинх("Удалить выбранные строки?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
УдалитьСтрокиНаСервере();
КонецЕсли;
КонецПроцедуры
Код читается почти как старый модальный, но модальности тут нет: процедура помечена Асинх, а Ждать приостанавливает только её, не блокируя клиент. Аналогично работают ПредупреждениеАсинх(), ВвестиЧислоАсинх(), ВвестиСтрокуАсинх(), ВвестиДатуАсинх().
Ждать можно писать только внутри процедуры или функции с пометкой Асинх. И проверьте режим совместимости конфигурации: если он ниже 8.3.18, ключевые слова не будут доступны.
Открытие своей формы с ожиданием результата
Старый вариант — ОткрытьФормуМодально() или метод формы ОткрытьМодально(). Новый — ОткрытьФорму():
&НаКлиенте
Процедура ВыбратьПериод(Команда)
Оповещение = Новый ОписаниеОповещения("ВыбратьПериодЗавершение", ЭтотОбъект);
ОткрытьФорму("Обработка.МояОбработка.Форма.ВыборПериода", , ЭтаФорма, , , ,
Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ВыбратьПериодЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат; // пользователь закрыл форму крестиком
КонецЕсли;
Период = Результат;
КонецПроцедуры
В вызываемой форме результат возвращают так: Закрыть(ВыбранныйПериод). Значение из Закрыть() и попадёт в параметр Результат обработчика.
Таблица замен для быстрого перевода кода
| Модальный метод | Замена с оповещением | Замена с Асинх |
|---|---|---|
Вопрос() | ПоказатьВопрос() | Ждать ВопросАсинх() |
Предупреждение() | ПоказатьПредупреждение() | Ждать ПредупреждениеАсинх() |
ВвестиЧисло() | ПоказатьВводЧисла() | Ждать ВвестиЧислоАсинх() |
ВвестиСтроку() | ПоказатьВводСтроки() | Ждать ВвестиСтрокуАсинх() |
ВвестиДату() | ПоказатьВводДаты() | Ждать ВвестиДатуАсинх() |
ОткрытьФормуМодально() | ОткрытьФорму() с оповещением о закрытии | — |
Последний столбец пригодится, если у вас много коротких вопросов в одной процедуре: с Асинх они остаются в одном месте, без разбиения на обработчики.
Блокировка интерфейса, зависания и ошибка запрета модальности
Почему окно «зависает» за основным
В «Такси» блокирующая форма — отдельное окно операционной системы. Если пользователь в этот момент переключился в браузер или почту, то при возврате Windows может вывести на передний план основное окно 1С, а не блокирующее. Интерфейс выглядит мёртвым, хотя 1С просто ждёт ответа.
Такое часто принимают за зависание и снимают процесс через диспетчер задач. Не завершайте процесс 1cv8c.exe, пока не проверили Alt+Tab: несохранённые данные в открытых формах пропадут.
Вызовы с сервера
Модальные и блокирующие окна открываются только на клиенте. Если код, который показывает вопрос, оказался в серверной процедуре или общем модуле без флажка «Клиент», вызов не скомпилируется или упадёт. Решение — разбить логику: на сервере вычислить данные, на клиенте показать вопрос, в обработчике ответа снова вызвать сервер.
Хорошие практики при работе с окнами в разработке
- Не используйте модальные методы в новом коде даже там, где их разрешает режим. Конфигурацию рано или поздно откроют через веб-клиент.
- Задавайте кнопку по умолчанию осторожно. Для опасных действий («Удалить», «Провести с перезаписью») по умолчанию ставьте «Нет»: пользователь, нажавший Enter по привычке, ничего не сломает.
- Таймаут — только для неважных вопросов. Если окно закрывается само через 30 секунд, решите, какой ответ будет считаться выбранным, и укажите его параметром кнопки таймаута.
- Проверяйте
Неопределенов обработчике. Форму могут закрыть крестиком или клавишей Esc, и результат будет пустым. - Не вкладывайте вопросы друг в друга бесконечно. Цепочка из трёх-четырёх
ПоказатьВопрос()с обработчиками быстро становится нечитаемой. Если платформа позволяет — переходите наАсинх/Ждать, а для сложного сценария делайте одну форму с несколькими полями. - Выбирайте минимальный уровень блокировки.
БлокироватьОкноВладельцапочти всегда удобнее пользователю, чем блокировка всего интерфейса. - Внешние обработки для чужих баз пишите сразу асинхронно. Обработка с модальными вызовами откроется не у всех клиентов, а с асинхронными — у всех.
Частые вопросы
С какой версии платформы появилась настройка режима модальности?
Режим использования модальности появилось в платформе 8.3.3. Ключевые слова Асинх и Ждать — в 8.3.18.Влияет ли режим модальности на внешние обработки?
Можно ли сделать окно, которое не даёт работать с остальной программой, без модальности?
ОткрытьФорму() с режимом РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс. Пользователь не сможет переключиться, но код не будет остановлен.Работает ли модальность в обычных формах и толстом клиенте?
Что выбрать для перехода: оповещения или Асинх?
Асинх/Ждать, код короче и проще. Если конфигурация должна работать на старых платформах — ОписаниеОповещения.