Почему управляемая форма 1С открывается отдельным окном Windows и как это исправить?

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

При обновлении технологической платформы «1С:Предприятие 8.3» на релизы ветки 8.3.16 разработчики и пользователи часто сталкиваются с крайне неприятным поведением интерфейса. При определенных действиях стандартная управляемая форма обработки или документа внезапно открывается не внутри привычной панели вкладок программы, а в виде совершенно отдельного окна операционной системы Windows.

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

В этой статье мы подробно разберем, почему возникает данное поведение, проанализируем технические причины сбоя платформы и рассмотрим практические способы решения этой проблемы.

Выясняем причину: почему ломается интерфейс?

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

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

В результате этого «рассинхрона» движок отрисовки интерфейса «Такси» считает, что у вновь открываемой формы нет родительского окна-владельца. Свойство формы Окно автоматически инициализируется значением ОкноКлиентскогоПриложения (вместо системного значения Неопределено, которое отвечает за открытие формы во вкладке), и операционная система создает для формы отдельный независимый процесс отрисовки окна.

Проблемные и стабильные версии платформы

Проанализируем статистику проявления этого бага на различных релизах платформы:

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

Способ 1. Использование обработчика ожидания (Рекомендуемый программный обход)

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

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

Проанализируем пример кода. Предположим, у нас был проблемный код:


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

&НаКлиенте
Процедура ПослеВыбораРежима(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент <> Неопределено Тогда
        // ОШИБКА: Форма откроется в отдельном окне Windows на платформе 8.3.16!
        ОткрытьФорму("Обработка.МояОбработка.Форма.РабочееМесто");
    КонецЕсли;
КонецПроцедуры

Перепишем этот алгоритм с использованием безопасного вызова через обработчик ожидания:


&НаКлиенте
Перем ИмяФормыДляОткрытия; // Переменная модуля для передачи контекста

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

&НаКлиенте
Процедура ПослеВыбораРежима(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент <> Неопределено Тогда
        // Сохраняем имя формы в переменную модуля для последующего вызова
        ИмяФормыДляОткрытия = "Обработка.МояОбработка.Форма.РабочееМесто";
        
        // Подключаем однократный обработчик с минимальной задержкой в 0.1 секунды
        ПодключитьОбработчикОжидания("ОткрытьФормуПослеПаузы", 0.1, Истина);
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьФормуПослеПаузы() Экспорт
    // За 0.1 секунды фокус гарантированно возвращается на основное окно 1С.
    // Форма откроется корректно — в новой вкладке приложения!
    ОткрытьФорму(ИмяФормыДляОткрытия);
КонецПроцедуры

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

Способ 2. Изменение бизнес-логики (Открытие формы до диалога)

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

В этом случае цепочка вызовов не прерывается потерей фокуса главного окна, так как сама открываемая форма уже создана в правильном контексте и привязана к родительскому окну.

Способ 3. Кардинальное решение — Обновление платформы

Несмотря на наличие стабильных программных обходных путей, лучшим решением проблемы будет обновление технологической платформы. Рекомендуется обновить тонкие и толстые клиенты пользователей, а также серверную часть «1С:Предприятия» до релизов 8.3.17.1032 и выше. Переход на актуальные версии полностью устраняет баг без необходимости внесения изменений в конфигурацию и написания дополнительного программного кода.

← На главную