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

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

Модальные окна в 1С 8.3: что это и как их использовать

Что такое модальные окна в 1С 8.3, как открыть форму модально, методы ОткрытьФормуМодально и ПоказатьВопрос, типичные ошибки и ограничения режима модальности.

Модальное окно в 1С 8.3 — это форма или диалог, который блокирует работу с остальными окнами приложения до тех пор, пока пользователь не закроет его. Пока модальное окно открыто, нельзя переключиться на другой документ, справочник или отчёт: платформа ждёт ответа пользователя. Классические примеры — вопрос «Записать изменения?», диалог выбора файла, предупреждение об ошибке.

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

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

Что такое модальность и как она работает

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

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

Важно понимать разницу между модальным и блокирующим окном. Блокирующее окно перекрывает только родительскую форму, а не весь интерфейс. В управляемом приложении 1С именно блокирующие окна стали стандартным решением, потому что они лучше вписываются в многодокументный интерфейс.

Какие методы открывают модальные окна

Во встроенном языке 1С есть целая группа методов, работающих в модальном режиме. К ним относятся: Вопрос() — задаёт вопрос с кнопками и возвращает код ответа; Предупреждение() — показывает сообщение с ожиданием; ОткрытьФормуМодально() — открывает произвольную форму и возвращает результат её закрытия; ВвестиЗначение(), ВвестиСтроку(), ВвестиЧисло(), ВвестиДату() — запрашивают данные у пользователя.

Также модально работают диалоги выбора файла через ДиалогВыбораФайла с методом Выбрать() и метод ОткрытьЗначение() для просмотра значения. Все эти вызовы объединяет одно: код после вызова не выполняется, пока пользователь не ответит.

Пример классического модального вызова вопроса:

Результат = Вопрос("Удалить помеченные элементы?", РежимДиалогаВопрос.ДаНет);

Если Результат = КодВозвратаДиалога.Да Тогда

УдалитьЭлементы();

КонецЕсли;

Асинхронная альтернатива: почему от модальности отказываются

Начиная с версии платформы 8.3, фирма «1С» последовательно выводит модальные вызовы из использования. Главная причина — веб-клиент и тонкий клиент через веб-сервер: синхронная остановка кода в ожидании ответа плохо совместима с архитектурой браузерных приложений. Кроме того, модальные окна ухудшают работу в многодокументном интерфейсе, блокируя всё приложение ради одного вопроса.

Вместо модальных методов предлагаются асинхронные аналоги с префиксом «Показать»: ПоказатьВопрос(), ПоказатьПредупреждение(), ПоказатьВводЗначения(), ПоказатьВводСтроки(). Для форм вместо ОткрытьФормуМодально() используется ОткрытьФорму() с параметром ОписаниеОповещенияОЗакрытии и свойством РежимОткрытияОкна = БлокироватьОкноВладельца.

Разница принципиальная: асинхронный метод не останавливает выполнение кода, а регистрирует процедуру-обработчик, которая будет вызвана, когда пользователь ответит. Продолжение логики переносится в эту процедуру:

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

ПоказатьВопрос(Оповещение, "Удалить элементы?", РежимДиалогаВопрос.ДаНет);

&НаКлиенте

Процедура ПослеОтветаНаВопрос(Результат, ДопПараметры) Экспорт

Если Результат = КодВозвратаДиалога.Да Тогда

УдалитьЭлементы();

КонецЕсли;

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

Настройка режима использования модальности в конфигурации

У корня конфигурации есть свойство «Режим использования модальности» с тремя значениями: «Использовать», «Использовать с предупреждениями» и «Не использовать». В режиме «Использовать с предупреждениями» модальные вызовы работают, но в журнал регистрации или окно сообщений выводятся предупреждения — это удобно на этапе постепенного переписывания кода.

Чтобы найти все модальные вызовы в конфигурации, выполните глобальный поиск по конфигуратору (Ctrl+Shift+F) по строкам: «Вопрос(», «Предупреждение(», «ОткрытьФормуМодально», «ВвестиЗначение», «ВвестиСтроку», «ВвестиЧисло», «ВвестиДату», «ОткрытьЗначение». Также полезно поискать метод Выбрать() у диалогов выбора файла.

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

Как заменить модальный вызов на асинхронный
  1. 1
    Найдите модальный вызов (например, Вопрос или ОткрытьФормуМодально) в модуле
  2. 2
    Создайте экспортную процедуру-обработчик с параметрами Результат и ДополнительныеПараметры
  3. 3
    Сформируйте объект ОписаниеОповещения с именем этой процедуры и контекстом
  4. 4
    Замените вызов на ПоказатьВопрос или ОткрытьФорму с передачей оповещения
  5. 5
    Перенесите весь код, который шёл после модального вызова, в тело обработчика
  6. 6
    Проверьте работу сценария в тонком и, при необходимости, в веб-клиенте

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

Типовая задача — открыть форму выбора или настроек так, чтобы пользователь не мог уйти в другое окно, и получить выбранное значение обратно. В асинхронной модели это делается через параметры ОткрытьФорму(): передаётся описание оповещения о закрытии, а режим открытия устанавливается в «Блокировать окно владельца».

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

ПараметрыФормы = Новый Структура("РежимВыбора", Истина);

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

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы, ЭтотОбъект, , , , Оповещение,

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

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

Сравнение подходов

Модальный вызов (Вопрос, ОткрытьФормуМодально)

Код простой и линейный, результат сразу в следующей строке. Не работает при запрещённой модальности, проблемы в веб-клиенте, блокирует весь интерфейс.

Асинхронный вызов (ПоказатьВопрос, ОткрытьФорму с оповещением)

Работает везде, соответствует современным требованиям платформы. Минус — логика дробится на процедуры-обработчики, код сложнее читать.

Блокирующее окно владельца

Компромисс: форма не даёт работать с родительским окном, но не блокирует всё приложение. Рекомендуемый вариант для форм выбора и настроек.

Типичные ошибки и ограничения

Самая частая ошибка — использование модальных методов в конфигурации с запрещённой модальностью. Проявляется сообщением «Использование модальных окон в данном режиме запрещено» в момент вызова. Лечится только переписыванием кода на асинхронные методы; снижать режим модальности ради старой доработки не стоит — это создаст проблемы при обновлениях.

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

Третья группа проблем — неверная работа с оповещениями: неэкспортная процедура-обработчик (директива Экспорт обязательна), неверное число параметров обработчика, обращение к переменным, которые к моменту срабатывания оповещения уже недоступны. Дополнительные данные передавайте через параметр ДополнительныеПараметры описания оповещения.

Типичные ошибки
01
Вызов Вопрос() при запрещённой модальности — код падает с ошибкой в момент выполнения
02
Модальный вызов в серверной процедуре или фоновом задании — интерактивные методы там недоступны
03
Неэкспортный обработчик оповещения — платформа не сможет его вызвать, получите ошибку
04
Продолжение кода сразу после ПоказатьВопрос() вместо переноса в обработчик — логика выполняется до ответа пользователя
05
Ожидание, что ОткрытьФорму вернёт значение как ОткрытьФормуМодально — результат приходит только через оповещение

Как проверить, что всё работает правильно

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

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

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

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

Открытие диалога
Норма

Окно появляется, код продолжает работу корректно, результат приходит в обработчик

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

Ошибка «Использование модальных окон запрещено» или обработчик не вызывается

Отмена пользователем
Норма

В обработчик приходит Неопределено или КодВозвратаДиалога.Отмена, логика это обрабатывает

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

При отмене выполняется действие, как будто пользователь согласился

Работа в веб-клиенте
Норма

Диалоги и формы открываются, выбор файлов работает через расширение

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

Диалог не появляется или сценарий обрывается без сообщений

Если вы пользователь, а не разработчик, и модальное окно «зависло» — чаще всего оно просто скрылось за другими окнами. Проверьте панель задач и переключитесь между окнами через Alt+Tab: заблокированное приложение обычно «оживает» после того, как вы найдёте и закроете скрытый диалог.

Итог

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

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

Частые вопросы о модальных окнах в 1С 8.3

Почему появляется ошибка «Использование модальных окон в данном режиме запрещено»?

В свойствах конфигурации установлен режим использования модальности «Не использовать», а код содержит модальные методы — Вопрос, Предупреждение, ОткрытьФормуМодально и подобные. Решение — переписать вызовы на асинхронные аналоги с описанием оповещения. Менять режим конфигурации на «Использовать» не рекомендуется, особенно в типовых решениях.

Чем ОткрытьФормуМодально отличается от ОткрытьФорму?

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

Как получить значение из открытой формы без модальности?

Передайте в ОткрытьФорму параметр с описанием оповещения о закрытии, а в открываемой форме завершайте работу вызовом Закрыть(Результат). Переданное значение придёт первым параметром в процедуру-обработчик. Для форм выбора в режиме выбора результат доставляется автоматически через обработку выбора.

Работают ли модальные окна в веб-клиенте?

Классические модальные вызовы в веб-клиенте либо не работают, либо ведут себя иначе — это одна из причин отказа от модальности в платформе. Асинхронные методы (ПоказатьВопрос, ПоказатьПредупреждение и др.) работают во всех клиентах единообразно, поэтому для решений с веб-доступом подходят только они.

Что делать, если модальное окно «повесило» программу и ничего не нажимается?

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

Нужно ли переписывать старые доработки с модальными окнами?

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