Почему ПоказатьВопрос сразу закрывается при вызове из процедуры ПриОткрытии и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

При разработке внешних обработок в управляемом интерфейсе разработчики нередко сталкиваются с неприятным поведением диалоговых окон: метод ПоказатьВопрос или ПоказатьПредупреждение, вызванный в обработчике события ПриОткрытии, мгновенно исчезает с экрана. При этом если запустить ту же самую обработку через стандартное меню Файл — Открыть, окно с вопросом отображается штатно и дожидается реакции пользователя. Но стоит подключить обработку через подсистему БСП Дополнительные отчеты и обработки, как диалог мелькает на доли секунды и завершается со значением КодВозвратаДиалога.Таймаут или КодВозвратаДиалога.Отмена.

Выясним причину такого поведения платформы 1С:Предприятие и разберем проверенные варианты корректного решения данной задачи.

Почему происходит мгновенное закрытие диалога?

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

  1. В процедуре ПриОткрытии вызывается метод ПоказатьВопрос, создающий дочернее всплывающее окно вопроса.
  2. Процедура ПриОткрытии завершает свое выполнение, после чего платформа в фоновом режиме выполняет обязательную финальную стадию — принудительную активацию открытой формы.
  3. Смена фокуса ввода и повторная активация родительской формы сбивают состояние немодального диалога, в результате чего платформа принудительно гасит всплывающее окно по таймауту.
  4. При запуске через подсистему БСП ситуация усугубляется тем, что форма открывается через служебные клиентские механизмы (командный интерфейс дополнительных обработок). БСП производит дополнительные манипуляции с окнами (закрытие окна списка обработок, передача контекста), что гарантированно перехватывает фокус.

Стандарты разработки 1С прямо запрещают интерактивные взаимодействия с пользователем в процедурах ПередОткрытием и ПриОткрытии. Эти процедуры предназначены только для настройки параметров формы и ее элементов.

Решение 1. Использование однократного обработчика ожидания

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

Разберем по шагам реализацию этого подхода:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Подключаем однократный обработчик с минимальным интервалом 0.1 секунды
    ПодключитьОбработчикОжидания("ЗадатьВопросПользователю", 0.1, Истина);
КонецПроцедуры

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

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

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

Решение 2. Использование асинхронных методов (для режима без совместимости с 8.3.17)

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

Посмотрим на пример асинхронной процедуры, запускаемой через обработчик ожидания:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ПодключитьОбработчикОжидания("ЗадатьВопросАсинхронно", 0.1, Истина);
КонецПроцедуры

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

Решение 3. Перенос вопроса в команду БСП (архитектурно правильный подход)

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

В подсистеме дополнительных отчетов и обработок БСП предусмотрен тип команды ВызовКлиентскогоМетода. С его помощью можно сначала задать вопрос пользователю в интерфейсе программы и открыть основную форму обработки только при положительном ответе.

Разберем реализацию такого сценария:

  1. В модуле объекта внешней обработки в функции СведенияОВнешнейОбработке для команды указываем вариант запуска ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода().
  2. В модуле формы обработки (или вспомогательной клиентской процедуре) перехватываем выполнение команды:

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

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

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

← На главную