При разработке специализированных интерфейсов на платформе 1С:Предприятие 7.7 (например, информационных киосков, прайс-чекеров или POS-терминалов) разработчики часто сталкиваются с нестандартным поведением оконной системы. Одной из наиболее распространенных и трудноуловимых проблем является потеря фокуса ввода формой при программном переключении слоев или при срабатывании периодических фоновых процессов (таких как ОбработкаОжидания).
В этой статье мы подробно разберем, почему переключение слоев формы приводит к «уходу» фокуса в Глобальный модуль, как работает маршрутизация внешних событий от торгового оборудования и как решить проблему потери фокуса с помощью простых, но эффективных приемов программирования и возможностей внешней компоненты FormEx.
Для начала проанализируем, как платформа 1С 7.7 взаимодействует с внешним оборудованием, например со сканером штрихкодов, подключенным через COM-порт или в режиме эмуляции клавиатуры. Когда сканер считывает штрихкод, драйвер торгового оборудования генерирует внешнее событие. Это событие передается в активное Win32-окно приложения 1С.
Платформа обрабатывает это событие по следующему строгому алгоритму:
ОбработкаВнешнегоСобытия(), событие передается именно в этот модуль. Локальный обработчик перехватывает штрихкод и выполняет поиск товара.ОбработкаВнешнегоСобытия(), платформа перенаправляет событие в Глобальный модуль.При проектировании информационного киоска разработчики часто реализуют режим экранной заставки (скринсейвера) прямо внутри одной формы, переключая видимые слои. Например, слой Товар отображает информацию о ценах, а слой Заставка показывает бегущую строку с призывом отсканировать товар. Переключение слоев выполняется с помощью метода ИспользоватьСлой().
В момент переключения слоев платформа 1С скрывает элементы управления текущего слоя и делает видимыми элементы нового. Если на скрываемом слое находился элемент (например, кнопка или текстовое поле ввода), который обладал фокусом ввода, операционная система Windows фиксирует уничтожение или скрытие активного элемента. В этот момент фокус ввода «сбрасывается» с формы, и активным элементом становится само главное окно 1С (контейнер MDI). Из-за этого локальная процедура ОбработкаВнешнегоСобытия() перестает реагировать на сканер, и все отсканированные штрихкоды уходят в Глобальный модуль, не пробуждая интерфейс киоска.
Казалось бы, решить проблему должен стандартный метод платформы Активизировать(). В синтакс-помощнике 1С 7.7 указано следующее:
«Пустое имя элемента диалога используется для активизации всей формы.»
Однако на практике вызов метода Активизировать() без параметров (или передача пустой строки) после смены слоев не дает никакого эффекта. Платформа визуально выводит форму на передний план, но реальный фокус ввода (Win32 caret/focus) не привязывается ни к одному активному элементу. Форма зависает в «полуактивном» состоянии, при котором внешние события продолжают игнорироваться локальным модулем.
Для того чтобы гарантированно вернуть фокус на форму и заставить локальный модуль обрабатывать сигналы сканера штрихкодов, применим проверенный временем трюк. Мы разместим на каждом из слоев по одному невидимому элементу управления и будем принудительно активизировать их при программном переключении интерфейса.
Выполним следующие шаги:
Заставка создадим обычный текстовый реквизит (или поле ввода), зададим ему идентификатор, например, Хрень (или РеквизитФокусаЗаставка). Чтобы этот элемент не портил внешний вид экрана, мы можем уменьшить его размер до 1x1 пикселя или вынести его координаты за пределы видимой области формы.Товар создадим аналогичный текстовый реквизит с идентификатором Хрень2 (или РеквизитФокусаТовар).Активизировать() с явным указанием имени созданных элементов-заглушек.Рассмотрим, как будет выглядеть программный код модулей при реализации этого алгоритма:
// Процедура перехода в режим экранной заставки (скринсейвер)
Процедура Заставка()
// Отключаем обработку ожидания, чтобы исключить циклическое срабатывание
Расш.ОбработкаОжидания("Заставка", 0);
// Переключаем интерфейс на слой заставки
Форма.ИспользоватьСлой("Заставка", 2);
Побежали3 = 1; // Флаг запуска анимации бегущей строки
Расш.ЦветФона = 0; // Задаем черный цвет фона для экономии ресурса экрана
// Принудительно обновляем форму для отрисовки изменений
Форма.Обновить();
// КЛЮЧЕВОЙ МОМЕНТ: Активизируем скрытый элемент на слое "Заставка"
// Это возвращает фокус ввода на саму форму!
Активизировать("Хрень");
КонецПроцедуры
// Процедура возврата формы в рабочий режим при сканировании или нажатии на экран
Процедура Разбудить()
// Заново инициализируем обработку ожидания на заданное время (например, 60 секунд)
Расш.ОбработкаОжидания("Заставка", 1000 * Константа.ВремяЗастКиоска);
// Переключаем интерфейс на рабочий слой с информацией о товаре
Форма.ИспользоватьСлой("Товар", 2);
Расш.ЦветФона = -1; // Возвращаем стандартный системный цвет фона
Побежали3 = 0; // Останавливаем анимацию бегущей строки
Форма.Обновить();
// КЛЮЧЕВОЙ МОМЕНТ: Активизируем элемент на рабочем слое
Активизировать("Хрень2");
КонецПроцедуры
Благодаря явной активации конкретного реквизита на видимом слое, операционная система Windows мгновенно возвращает фокус ввода на форму. С этого момента процедура ОбработкаВнешнегоСобытия() в модуле нашей формы снова начинает исправно принимать сигналы от сканера штрихкодов.
При использовании внешней компоненты FormEx для кастомизации интерфейса (управление цветом фона, скрытие заголовков, максимизация окон) разработчики часто сталкиваются с тем, что предопределенные процедуры компоненты ведут себя нестабильно или вовсе не вызываются, если форма открыта в модальном режиме.
Проанализируем жизненный цикл событий FormEx и выясним, почему процедуры ПослеОткрытия() и ПослеСозданияФормы() могут не срабатывать:
ПослеСоздания(), проверяя режим работы формы.Рассмотрим правильный шаблон инициализации расширения формы для модального режима работы информационного киоска:
Процедура ПриОткрытии()
// Инициализируем объекты FormEx
// Важно: в ПриОткрытии() самого окна Win32 еще не существует,
// поэтому любые прямые манипуляции с геометрией окна здесь ошибочны!
фрм = СоздатьОбъект("Форма");
фрм.УстановитьФорму(Форма);
КонецПроцедуры
// Используем событие "ПослеСоздания" для настройки визуального стиля окна
Процедура ПослеСоздания()
// Создаем объекты для работы с окнами и расширением формы
Окно = СоздатьОбъект("Окна");
Расш = СоздатьОбъект("РасширениеФормы");
Расш.УстановитьФорму(Форма);
// Переводим форму в полноэкранный режим (Kiosk Mode)
Окно.НаПереднийПлан(Форма);
Окно.Максимизировать(Форма);
Окно.ЦентрироватьОкно(Форма);
// Скрываем строку состояния и убираем стандартные рамки окна 1С
Окно.ПоказыватьСтрокуСостояния(0);
Окно.СтильОкна(Форма, 2); // Стиль без рамок и заголовков
// Инициализируем таймер перехода в режим заставки
ВремяЗастКиоска = Константа.ВремяЗастКиоска;
Расш.ОбработкаОжидания("Заставка", 1000 * ВремяЗастКиоска);
КонецПроцедуры
Этот шаблон гарантирует корректную отработку всех методов FormEx по управлению стилями окна без мерцания интерфейса и зависания платформы 1С:Предприятие 7.7.
Применение скрытых полей-заглушек в сочетании с правильной обработкой жизненного цикла событий FormEx позволяет создавать надежные, стабильные и эстетичные решения для информационных терминалов, работающих в режиме 24/7 без необходимости постоянного вмешательства системных администраторов.