При разработке внешних обработок в управляемом интерфейсе разработчики нередко сталкиваются с неприятным поведением диалоговых окон: метод ПоказатьВопрос или ПоказатьПредупреждение, вызванный в обработчике события ПриОткрытии, мгновенно исчезает с экрана. При этом если запустить ту же самую обработку через стандартное меню Файл — Открыть, окно с вопросом отображается штатно и дожидается реакции пользователя. Но стоит подключить обработку через подсистему БСП Дополнительные отчеты и обработки, как диалог мелькает на доли секунды и завершается со значением КодВозвратаДиалога.Таймаут или КодВозвратаДиалога.Отмена.
Выясним причину такого поведения платформы 1С:Предприятие и разберем проверенные варианты корректного решения данной задачи.
Почему происходит мгновенное закрытие диалога?
Проанализируем механику работы клиентского приложения при открытии управляемой формы. Событие ПриОткрытии выполняется в тот момент, когда форма уже создана на клиенте, но процесс ее окончательного размещения в графической подсистеме и передачи ей фокуса ввода еще не завершен. Вызов немодального блокирующего окна поверх формы в этой фазе приводит к конфликту оконной подсистемы платформы:
ПриОткрытии вызывается метод ПоказатьВопрос, создающий дочернее всплывающее окно вопроса.ПриОткрытии завершает свое выполнение, после чего платформа в фоновом режиме выполняет обязательную финальную стадию — принудительную активацию открытой формы.Стандарты разработки 1С прямо запрещают интерактивные взаимодействия с пользователем в процедурах ПередОткрытием и ПриОткрытии. Эти процедуры предназначены только для настройки параметров формы и ее элементов.
Самый простой и надежный способ решить проблему внутри формы — отложить показ вопроса до момента, пока платформа полностью не завершит отрисовку и захват фокуса. Для этого в процедуре ПриОткрытии подключается процедура через обработчик ожидания с минимальной задержкой.
Разберем по шагам реализацию этого подхода:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем однократный обработчик с минимальным интервалом 0.1 секунды
ПодключитьОбработчикОжидания("ЗадатьВопросПользователю", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ЗадатьВопросПользователю()
Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Продолжить выполнение операции?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Выполняем требуемые действия
Иначе
ЭтаФорма.Закрыть();
КонецЕсли;
КонецПроцедуры
Параметр Истина в третьем аргументе метода ПодключитьОбработчикОжидания указывает платформе выполнить вызов только один раз. Задержки в 0.1 секунды достаточно для того, чтобы платформа активировала окно формы и освободила очередь системных событий. После этого окно вопроса открывается без сбоев.
Если конфигурация работает без режима совместимости с устаревшими версиями платформы (режим 8.3.18 и выше), мы можем использовать конструкцию асинхронных функций с оператором Ждать. Однако вызывать их следует также после завершения инициализации окна.
Посмотрим на пример асинхронной процедуры, запускаемой через обработчик ожидания:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ЗадатьВопросАсинхронно", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Асинх Процедура ЗадатьВопросАсинхронно()
Ответ = Ждать ВопросАсинх("Загрузить исходные данные?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
// Логика при подтверждении
Иначе
ЭтаФорма.Закрыть();
КонецЕсли;
КонецПроцедуры
Рассмотрим ситуацию, когда вопрос задается для того, чтобы определить, требуется ли открывать форму обработки вообще. Открывать пустую форму только ради того, чтобы спросить пользователя и затем закрыть ее при отказе — неоптимальное архитектурное решение.
В подсистеме дополнительных отчетов и обработок БСП предусмотрен тип команды ВызовКлиентскогоМетода. С его помощью можно сначала задать вопрос пользователю в интерфейсе программы и открыть основную форму обработки только при положительном ответе.
Разберем реализацию такого сценария:
СведенияОВнешнейОбработке для команды указываем вариант запуска ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода().
&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения) Экспорт
Оповещение = Новый ОписаниеОповещения("ПослеПодтвержденияЗапуска", ЭтотОбъект, ПараметрыВыполнения);
ПоказатьВопрос(Оповещение, "Открыть рабочее место обработки?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПодтвержденияЗапуска(Результат, ПараметрыВыполнения) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Открываем форму обработки явно только после согласия
ОткрытьФорму("ВнешняяОбработка." + ПараметрыВыполнения.ИмяОбработки + ".Форма.Форма");
КонецЕсли;
КонецПроцедуры
Такой подход полностью исключает появление «мигающих» пустых окон и соответствует стандартам разработки управляемого интерфейса 1С.