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

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

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

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

Выясняем причину: почему фокус возвращается на исходную форму?

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

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

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

Рассмотрим детально рабочие способы обхода этой особенности платформы.

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

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

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


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

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

При таком подходе событие нажатия кнопки завершается штатно, фокус «успокаивается» на исходной форме, а затем срабатывает фоновое событие, которое открывает форму печати и делает её активной на переднем плане.

Решение 2. Блокировка окна владельца

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

Рассмотрим структуру вызова функции ОткрытьФорму. Восьмым параметром она принимает значение системного перечисления РежимОткрытияОкнаФормы. По умолчанию используется режим Независимый, но мы можем принудительно передать значение БлокироватьОкноВладельца.

Посмотрим на пример практической реализации:


// Получим ключ уникальности открываемой формы.
КлючУникальности = Строка(Новый УникальныйИдентификатор);

ПараметрыОткрытия = Новый Структура("ИмяМенеджераПечати,ИменаМакетов,ПараметрКоманды", 
    ИмяМенеджераПечати, ИменаМакетов, МассивОбъектов);

// Используем 8-й параметр для жесткой блокировки окна владельца
ОткрытьФорму(
    "ОбщаяФорма.ПечатьДокументов", 
    ПараметрыОткрытия, 
    ВладелецФормы, 
    КлючУникальности, 
    , // Окно (пропускаем)
    , // НавигационнаяСсылка (пропускаем)
    , // ОписаниеОповещенияЗакрытия (пропускаем)
    РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
);

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

Решение 3. Отмена стандартной обработки событий

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

Для этого в обработчике события необходимо установить параметр СтандартнаяОбработка в значение Ложь:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    // Отменяем стандартное поведение платформы по активизации строки списка
    СтандартнаяОбработка = Ложь;
    
    // Теперь вызываем нашу форму - она корректно захватит фокус ввода
    ОткрытьФормуПечати();
    
КонецПроцедуры

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

Решение 4. Использование механизма Расширений конфигурации

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

Если мы попытаемся вызвать метод ЭтаФорма.Активизировать() непосредственно в событии ПриОткрытии или ПриСозданииНаСервере целевой формы, это не даст результата, поскольку вызовы будут перекрыты последующим завершением транзакции формы-отправителя.

Поэтому в расширении для целевой формы мы также задействуем отложенный вызов через обработчик ожидания:


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

&НаКлиенте
Процедура Изм_ПринудительнаяАктивизация()
    
    // Активизируем форму после того, как все клиентские потоки завершились
    ЭтаФорма.Активизировать();
    
КонецПроцедуры

Этот способ позволяет решить проблему локально внутри открываемого объекта, не заботясь о том, из какого места конфигурации и при каких обстоятельствах он был вызван.

Решение 5. Использование типовых механизмов БСП (Библиотеки Стандартных Подсистем)

Если вы работаете в современной конфигурации (например, «1С:Управление торговлей 11», «1С:ERP Управление предприятием» или «1С:Комплексная автоматизация»), ручной вызов метода ОткрытьФорму для печати документов является устаревшим подходом.

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


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

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

Подведем итоги

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

← На главную