Как работает клавиатурный сканер и перехват клавиш FormEx в 1С 7.7?

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

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

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

Архитектура перехвата клавиатурных событий: FormEx против Драйвера

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

  1. Использование внешнего драйвера торгового оборудования (например, АТОЛ, Штрих-М или ScanOpos). Драйвер перехватывает поток ввода, собирает символы по префиксам/суффиксам и генерирует штатное ОбработкаВнешнегоСобытия().
  2. Перехват событий клавиатуры на уровне платформы 1С с помощью внешней компоненты FormEx через предопределенные процедуры контроля фокуса и клавиатуры.

Рассмотрим, как распределяются приоритеты перехвата. Как только клавиша нажимается на физическом устройстве, Windows отправляет сообщение в очередь потока приложения 1С. Компонента FormEx внедряет глобальный перехватчик (так называемый клавиатурный хук — Keyboard Hook). Этот хук срабатывает раньше, чем стандартная очередь сообщений 1С дойдет до оконных элементов управления.

Порядок обработки каждого символа выглядит следующим образом:

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

Ответ на Вопрос №1: Работает ли событие отжатия клавиши?

Выясним, срабатывает ли процедура ПриОтжатииКнопкиКлавиатуры() при сканировании штрихкода клавиатурным сканером с активным драйвером.

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

Однако на практике использовать событие отжатия клавиши для логики распознавания штрихкодов не рекомендуется. Вся необходимая информация о вводимом символе уже доступна в момент нажатия, а обработка отпускания клавиши лишь создаст лишнюю нагрузку на процессор при обработке плотного потока данных.

Ответ на Вопрос №2: Сканирование в поле ввода с суффиксом Enter (#13)

Проанализируем ситуацию: пользователь установил курсор в активное Поле ввода на форме 1С и отсканировал штрихкод. Сканер настроен на эмуляцию клавиатуры, в системе подключен драйвер, а в качестве суффикса задан символ возврата каретки (код #13, клавиша Enter). Какова будет последовательность выполнения процедур?

Здесь возможны два сценария в зависимости от стабильности работы драйвера:

Сценарий А: Штатная работа драйвера

Драйвер сканера успевает корректно перехватить весь поток символов до того, как они попадут на отрисовку в операционную систему. Драйвер накапливает символы во внутреннем буфере. Как только приходит завершающий символ суффикса (код #13), драйвер прекращает сбор данных и инициирует асинхронное системное событие.

В результате:

Сценарий Б: Сбой или задержка драйвера (типично для RDP и Wi-Fi)

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

В результате:

Почему клавиатурный сканер сбоит в терминальном режиме (RDP)

Рассмотрим подробнее причины нестабильной работы связки клавиатурного сканера и драйвера в терминальной сессии по сети Wi-Fi. Внешний драйвер (например, АТОЛ) идентифицирует ввод со сканера по временным интервалам между символами. Скорость человеческого ввода на клавиатуре редко превышает 10 символов в секунду (интервал ~100 мс). Сканер же выдает поток с паузами в 5–15 миллисекунд.

При передаче нажатий клавиш через протокол RDP пакеты данных группируются и отправляются по сети неравномерно. Из-за джиттера (колебаний сетевой задержки) интервалы между символами штрихкода на стороне сервера могут искусственно увеличиваться до 50–150 мс. Драйвер считает, что эти символы вводит пользователь вручную, отключает режим перехвата и «высыпает» оставшуюся часть штрихкода прямо в активное текстовое поле, приводя к хаосу в интерфейсе.

Кроме того, при сканировании сложных двумерных кодов (например, DataMatrix для маркировки товаров) критически важным становится регистр символов. При передаче через RDP состояние клавиши Shift может инвертироваться или запаздывать, из-за чего валидный код маркировки превращается в нечитаемый набор символов.

Решение проблемы: Программный сканер на чистом FormEx

Чтобы избежать платных драйверов и гарантировать стопроцентную стабильность работы в терминальном режиме, разработчики 1С 7.7 часто отказываются от внешних драйверов сканера в пользу алгоритма программного накопления штрихкода средствами компоненты FormEx. Этот подход основан на замере времени между нажатиями клавиш непосредственно внутри движка 1С на стороне сервера.

Давайте разберем по шагам реализацию такого алгоритма в Глобальном модуле конфигурации.

Для начала объявим глобальные переменные для хранения буфера данных и времени последнего нажатия:


Перем глБуферСканера Экспорт;
Перем глВремяПредыдущегоНажатия Экспорт;

Затем напишем процедуру перехвата клавиатуры. Мы будем использовать системный счетчик миллисекунд для точного определения интервалов между нажатиями клавиш:


Процедура ПриНажатииКнопкиКлавиатуры(Контекст, КодКлавиши, Альт, Шифт, Контрл, ФСО)
    // Определяем текущее время в миллисекундах
    ТекущееВремя = _GetPerformanceCounter();
    Интервал = ТекущееВремя - глВремяПредыдущегоНажатия;
    глВремяПредыдущегоНажатия = ТекущееВремя;

    // Допустимый интервал для сканера — не более 35 миллисекунд
    Если (Интервал < 35) Или (глБуферСканера = "") Тогда
        // Обрабатываем символ
        Если КодКлавиши = 13 Тогда
            // Если пришел Enter (код 13), значит сканирование завершено
            Если ПустаяСтрока(глБуферСканера) = 0 Тогда
                // Блокируем стандартную обработку Enter в системе
                ФСО = 0;
                
                // Вызываем обработку полученного штрихкода
                ОбработатьПолученныйКод(глБуферСканера);
                глБуферСканера = "";
            КонецЕсли;
        ИначеЕсли (КодКлавиши >= 32) И (КодКлавиши <= 127) Тогда
            // Накапливаем печатные символы в буфер
            глБуферСканера = глБуферСканера + Симв(КодКлавиши);
            // Блокируем передачу символа в активное поле ввода на форме
            ФСО = 0;
        КонецЕсли;
    Иначе
        // Если интервал велик — это ввод обычного пользователя с клавиатуры.
        // Очищаем буфер, чтобы не мешать ручной работе.
        глБуферСканера = "";
    КонецЕсли;
КонецПроцедуры

Проанализируем работу этого алгоритма. Если пользователь нажимает клавиши вручную, интервал гарантированно превышает 35 миллисекунд. Переменная глБуферСканера мгновенно очищается, а флаг стандартной обработки ФСО остается равным единице, позволяя тексту печататься на экране. При чтении кода сканером интервалы ничтожно малы, программа блокирует передачу символов на экран через ФСО = 0, собирает их в переменную и обрабатывает штрихкод при поступлении суффикса.

Рекомендации по настройке торгового оборудования

Для достижения максимальной отказоустойчивости системы автоматизации рекомендуется следовать двум правилам:

  1. Перевод сканеров в режим виртуального COM-порта (USB-CDC). Это наиболее надежный способ работы. Данные от сканера передаются в операционную систему не посимвольно, а единым пакетом (буфером). В этом режиме полностью исключены сетевые задержки RDP и перепутанные регистры символов. При этом 1С получает готовое внешнее событие штатным образом.
  2. Использование FormEx при невозможности уйти от эмуляции клавиатуры. Если аппаратные ограничения или особенности инфраструктуры заставляют использовать сканер в режиме клавиатуры, откажитесь от внешних драйверов и используйте приведенный выше алгоритм программного перехвата на FormEx. Он работает внутри сессии 1С и не подвержен конфликтам драйверов.
← На главную