Как вернуть фокус на форму в 1С 7.7 при использовании слоев и внешней компоненты FormEx?

Программист 1С v7.7 Торговля и дистрибуция
← На главную

При разработке специализированных интерфейсов на платформе 1С:Предприятие 7.7 (например, информационных киосков, прайс-чекеров или POS-терминалов) разработчики часто сталкиваются с нестандартным поведением оконной системы. Одной из наиболее распространенных и трудноуловимых проблем является потеря фокуса ввода формой при программном переключении слоев или при срабатывании периодических фоновых процессов (таких как ОбработкаОжидания).

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

Физика процесса: почему пропадает фокус и ломается сканер штрихкодов?

Для начала проанализируем, как платформа 1С 7.7 взаимодействует с внешним оборудованием, например со сканером штрихкодов, подключенным через COM-порт или в режиме эмуляции клавиатуры. Когда сканер считывает штрихкод, драйвер торгового оборудования генерирует внешнее событие. Это событие передается в активное Win32-окно приложения 1С.

Платформа обрабатывает это событие по следующему строгому алгоритму:

  1. Система проверяет, существует ли в данный момент активная (находящаяся в фокусе) форма.
  2. Если такая форма открыта и в ее модуле определена предопределенная процедура ОбработкаВнешнегоСобытия(), событие передается именно в этот модуль. Локальный обработчик перехватывает штрихкод и выполняет поиск товара.
  3. Если форма открыта, но фокус с нее утерян (например, активным стало главное окно программы или фокус «завис» в пустоте), либо в модуле формы отсутствует процедура ОбработкаВнешнегоСобытия(), платформа перенаправляет событие в Глобальный модуль.

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

В момент переключения слоев платформа 1С скрывает элементы управления текущего слоя и делает видимыми элементы нового. Если на скрываемом слое находился элемент (например, кнопка или текстовое поле ввода), который обладал фокусом ввода, операционная система Windows фиксирует уничтожение или скрытие активного элемента. В этот момент фокус ввода «сбрасывается» с формы, и активным элементом становится само главное окно 1С (контейнер MDI). Из-за этого локальная процедура ОбработкаВнешнегоСобытия() перестает реагировать на сканер, и все отсканированные штрихкоды уходят в Глобальный модуль, не пробуждая интерфейс киоска.

Ограничение стандартного метода Активизировать()

Казалось бы, решить проблему должен стандартный метод платформы Активизировать(). В синтакс-помощнике 1С 7.7 указано следующее:

«Пустое имя элемента диалога используется для активизации всей формы.»

Однако на практике вызов метода Активизировать() без параметров (или передача пустой строки) после смены слоев не дает никакого эффекта. Платформа визуально выводит форму на передний план, но реальный фокус ввода (Win32 caret/focus) не привязывается ни к одному активному элементу. Форма зависает в «полуактивном» состоянии, при котором внешние события продолжают игнорироваться локальным модулем.

Пошаговое решение: принудительная активация через скрытый реквизит-заглушку

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

Выполним следующие шаги:

  1. Откроем форму нашей обработки в конфигураторе 1С 7.7.
  2. На слое Заставка создадим обычный текстовый реквизит (или поле ввода), зададим ему идентификатор, например, Хрень (или РеквизитФокусаЗаставка). Чтобы этот элемент не портил внешний вид экрана, мы можем уменьшить его размер до 1x1 пикселя или вынести его координаты за пределы видимой области формы.
  3. На слое Товар создадим аналогичный текстовый реквизит с идентификатором Хрень2 (или РеквизитФокусаТовар).
  4. В кодовой логике переключения слоев обязательно пропишем вызов метода Активизировать() с явным указанием имени созданных элементов-заглушек.

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


// Процедура перехода в режим экранной заставки (скринсейвер)
Процедура Заставка() 
    // Отключаем обработку ожидания, чтобы исключить циклическое срабатывание
    Расш.ОбработкаОжидания("Заставка", 0); 
    
    // Переключаем интерфейс на слой заставки
    Форма.ИспользоватьСлой("Заставка", 2);
    Побежали3 = 1; // Флаг запуска анимации бегущей строки
    Расш.ЦветФона = 0; // Задаем черный цвет фона для экономии ресурса экрана
    
    // Принудительно обновляем форму для отрисовки изменений
    Форма.Обновить();
    
    // КЛЮЧЕВОЙ МОМЕНТ: Активизируем скрытый элемент на слое "Заставка"
    // Это возвращает фокус ввода на саму форму!
    Активизировать("Хрень");  
КонецПроцедуры

// Процедура возврата формы в рабочий режим при сканировании или нажатии на экран
Процедура Разбудить() 
    // Заново инициализируем обработку ожидания на заданное время (например, 60 секунд)
    Расш.ОбработкаОжидания("Заставка", 1000 * Константа.ВремяЗастКиоска);
    
    // Переключаем интерфейс на рабочий слой с информацией о товаре
    Форма.ИспользоватьСлой("Товар", 2);
    Расш.ЦветФона = -1; // Возвращаем стандартный системный цвет фона
    Побежали3 = 0; // Останавливаем анимацию бегущей строки
    
    Форма.Обновить();
    
    // КЛЮЧЕВОЙ МОМЕНТ: Активизируем элемент на рабочем слое
    Активизировать("Хрень2");
КонецПроцедуры

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

Особенности инициализации интерфейса и работы событий FormEx в модальных окнах

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

Проанализируем жизненный цикл событий FormEx и выясним, почему процедуры ПослеОткрытия() и ПослеСозданияФормы() могут не срабатывать:

  1. ПослеОткрытия() (OnActivate): Это событие предназначено для выполнения действий после полной отрисовки окна на экране. Однако в модальных формах из-за особенностей блокировки потока сообщений платформой 1С это событие в большинстве старых версий FormEx попросту не вызывается. Поэтому переносить туда критически важный код инициализации нельзя.
  2. ПослеСозданияФормы() (OnCreateForm): Вызывается сразу после создания системного описания окна (HWND), но до его визуального отображения. Это идеальная точка для настройки внешнего вида окна: изменения стилей, скрытия рамок, максимизации. Это событие работает стабильно как в обычных, так и в модальных формах.
  3. Использование ПослеСоздания() в качестве альтернативы: В зависимости от версии FormEx и наличия в системе других компонент (например, 1С++), имя процедуры может отличаться. Рекомендуется использовать предопределенное событие ПослеСоздания(), проверяя режим работы формы.

Рассмотрим правильный шаблон инициализации расширения формы для модального режима работы информационного киоска:


Процедура ПриОткрытии()
    // Инициализируем объекты FormEx
    // Важно: в ПриОткрытии() самого окна Win32 еще не существует,
    // поэтому любые прямые манипуляции с геометрией окна здесь ошибочны!
    фрм = СоздатьОбъект("Форма");
    фрм.УстановитьФорму(Форма);
КонецПроцедуры

// Используем событие "ПослеСоздания" для настройки визуального стиля окна
Процедура ПослеСоздания()
    // Создаем объекты для работы с окнами и расширением формы
    Окно = СоздатьОбъект("Окна");
    Расш = СоздатьОбъект("РасширениеФормы");
    Расш.УстановитьФорму(Форма);
    
    // Переводим форму в полноэкранный режим (Kiosk Mode)
    Окно.НаПереднийПлан(Форма); 
    Окно.Максимизировать(Форма);
    Окно.ЦентрироватьОкно(Форма);
    
    // Скрываем строку состояния и убираем стандартные рамки окна 1С
    Окно.ПоказыватьСтрокуСостояния(0);
    Окно.СтильОкна(Форма, 2); // Стиль без рамок и заголовков
    
    // Инициализируем таймер перехода в режим заставки
    ВремяЗастКиоска = Константа.ВремяЗастКиоска;
    Расш.ОбработкаОжидания("Заставка", 1000 * ВремяЗастКиоска); 
КонецПроцедуры

Этот шаблон гарантирует корректную отработку всех методов FormEx по управлению стилями окна без мерцания интерфейса и зависания платформы 1С:Предприятие 7.7.

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

← На главную