При работе со сканерами штрихкодов в 1С часто возникает ситуация, когда оборудование используется в режиме эмуляции клавиатуры (HID-режим). Это удобно, так как не требует установки специализированных драйверов и настройки торгового оборудования. Однако такая простота порождает техническую проблему: после считывания кода сканер автоматически посылает символ Enter (возврат каретки), что заставляет платформу 1С переводить фокус на следующий элемент формы. В итоге поле ввода не очищается, а курсор «улетает», заставляя пользователя каждый раз возвращать его вручную.
В этой статье мы подробно разберем, почему стандартные методы типа ТекущийЭлемент не всегда срабатывают сразу, и как организовать стабильную работу с любыми моделями сканеров.
Разберем механику процесса. Сканер в режиме клавиатуры передает данные очень быстро. Последовательность событий выглядит так:
Если мы пытаемся вернуть фокус в обработчике события ПриИзменении или АвтоПодборТекста, возникает конфликт приоритетов. Программа выполняет ваш код по установке фокуса, но сразу после этого система отрабатывает штатное нажатие клавиши Enter, которое было в очереди событий, и благополучно уводит курсор дальше.
Проанализируем самый надежный способ обхода очереди событий — использование метода ПодключитьОбработчикОжидания. Этот метод позволяет выполнить процедуру возврата фокуса не мгновенно, а через микроскопическую паузу, когда системная обработка нажатия Enter уже завершена.
Рассмотрим пример кода для обычной формы. Допустим, наше поле называется ПолеВводаШтрихкода.
В модуле формы пропишем обработку события ПриИзменении:
Процедура ПолеВводаШтрихкодаПриИзменении(Элемент)
// Здесь выполняем поиск номенклатуры по считанному коду
Штрихкод = Элемент.Значение;
Если НЕ ПустаяСтрока(Штрихкод) Тогда
// Логика поиска и добавления товара
ДобавитьТоварПоШтрихкоду(Штрихкод);
// Очищаем поле сразу
Элемент.Значение = "";
// Подключаем возврат фокуса через короткий интервал (0.1 сек)
// Имя процедуры указываем в кавычках
ПодключитьОбработчикОжидания("ВернутьФокусВПолеВвода", 0.1, Истина);
КонецЕсли;
КонецПроцедуры
Затем создадим саму экспортную процедуру, которая вернет курсор на место:
Процедура ВернутьФокусВПолеВвода() Экспорт
// Для обычных форм важно переустановить текущий элемент
ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ПолеВводаШтрихкода;
КонецПроцедуры
Использование флага Истина в методе ПодключитьОбработчикОжидания гарантирует, что процедура выполнится только один раз. Это «читерский», но крайне эффективный способ поставить команду возврата фокуса в самый конец очереди событий приложения.
Если вы хотите решить проблему радикально и не зависеть от таймеров в коде 1С, проанализируем возможность настройки самого «железа». Почти каждый USB-сканер (даже самый дешевый) поддерживает программирование через специальные штрихкоды из инструкции.
Выясним последовательность действий:
В этом случае сканер перестанет посылать Enter после кода. Фокус будет оставаться в поле, так как система не получит команды перехода. Однако помните: при таком подходе событие ПриИзменении в 1С может не сработать автоматически, так как редактирование поля формально не закончено. Вам придется использовать событие АвтоПодборТекста или анализировать длину введенной строки.
Рассмотрим еще один архитектурный прием. На форме можно разместить невидимую (или вспомогательную) кнопку и установить в ее свойствах параметр КнопкаПоУмолчанию = Истина.
Как это работает: когда сканер посылает Enter, система имитирует нажатие этой кнопки. Мы можем перенести всю логику обработки в событие нажатия этой кнопки:
Процедура КнопкаПоУмолчаниюНажатие(Кнопка)
// Получаем текст из поля ввода
ТекстКода = ЭлементыФормы.ПолеВводаШтрихкода.Значение;
Если ЗначениеЗаполнено(ТекстКода) Тогда
// Обработка кода
ОбработатьШтрихкод(ТекстКода);
// Очистка
ЭлементыФормы.ПолеВводаШтрихкода.Значение = "";
КонецЕсли;
// Принудительный возврат
ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ПолеВводаШтрихкода;
КонецПроцедуры
Посмотрим на ситуацию под другим углом. Иногда полная очистка поля "" приводит к тому, что фокус теряется еще легче. Вместо очистки можно использовать метод выделения текста. В этом случае визуально поле будет заполнено, но при следующем сканировании новые данные полностью заменят старые.
Для реализации этого метода используем УстановитьГраницыВыделения:
// В обработчике ожидания или после обработки кода
ЭлементыФормы.ПолеВводаШтрихкода.УстановитьГраницыВыделения(0, СтрДлина(ЭлементыФормы.ПолеВводаШтрихкода.Значение));
Проанализируем различия платформ:
ТекущийЭлемент внутри обработчиков событий ввода часто игнорируется платформой из-за внутреннего стека вызовов. Обработчик ожидания — здесь единственный стабильный вариант.ЭтаФорма.ТекущийЭлемент = ... в связке с очисткой данных на сервере и возвратом на клиент.Подводя итог, если вы столкнулись с «зоопарком» сканеров, которые никто не хочет настраивать, оптимальным путем будет реализация обработчика ожидания. Это универсальный код, который корректно отработает на любом USB-сканере, независимо от того, какой суффикс в нем прошит «с завода».