В процессе автоматизации торговых операций разработчики часто сталкиваются с неприятной особенностью: если у пользователя на клавиатуре включен режим CapsLock, данные, передаваемые сканером штрихкодов в режиме эмуляции клавиатуры, инвертируются. Например, вместо ожидаемого кода So060616001020 система получает sO060616001020. Для регистрозависимых кодов, таких как коды маркировки «Честный ЗНАК» (DataMatrix), это критично — код становится невалидным, и бизнес-процесс прерывается.
В этой статье мы подробно разберем, почему штатные средства 1С не позволяют напрямую определить состояние клавиш, и рассмотрим несколько эффективных способов решения этой проблемы: от настройки торгового оборудования до программных методов обхода ограничений.
Проанализируем ситуацию: многие начинающие разработчики советуют просто использовать функцию Врег() (приведение к верхнему регистру) для входящей строки. Однако, как справедливо замечено в обсуждении, это решение работает только для регистронезависимых штрихкодов (состоящих только из цифр или только из букв одного регистра). Если ваш штрихкод содержит символы разных регистров, принудительное изменение регистра безвозвратно испортит данные. Нам нужно именно исходное состояние данных, зашитых в коде.
Выясним главную причину проблемы: использование режима Keyboard Wedge (эмуляция клавиатуры). В этом режиме операционная система воспринимает сканер как человека, быстро нажимающего на кнопки. Следовательно, настройки клавиатуры (регистр и раскладка) влияют на результат.
Самым надежным решением является перевод сканера в режим эмуляции COM-порта (через Native API). Разберем преимущества этого метода:
ВнешнееСобытие исключает случайные вставки символов в активные текстовые поля форм.Для реализации этого метода необходимо найти в руководстве к вашему сканеру специальный настроечный штрихкод (обычно называется USB Serial Emulation или Enable Uni-Directional USB Serial Mode) и перенастроить драйвер в 1С в разделе «Подключаемое оборудование».
Если по каким-то причинам вы не можете перевести сканер в режим COM-порта, проанализируем возможности самого устройства. Большинство современных сканеров (Zebra, Honeywell, Datalogic) имеют внутреннюю настройку Caps Lock Override.
Рассмотрим, как это работает: сканер перед отправкой каждого символа проверяет состояние CapsLock на компьютере и, если он включен, программно эмулирует нажатие клавиши Shift для инверсии обратно в нужный регистр. Чтобы активировать эту функцию, нужно отсканировать соответствующий служебный код из инструкции к конкретной модели сканера.
Если нам необходимо программно предупредить пользователя о включенном CapsLock непосредственно в интерфейсе 1С, мы можем обратиться к возможностям операционной системы. Поскольку встроенной функции CapsLockНажат() не существует, воспользуемся вызовом функции из user32.dll.
Посмотрим на пример реализации (этот метод требует возможности вызова внешних функций, что доступно в среде Windows):
// Пример логики для определения состояния клавиши
// Требуется использование внешней компоненты, например, DynamicWrapperX
// или написание собственной обертки
Функция CapsLockВключен()
Попытка
Wrapper = Новый COMОбъект("DynamicWrapperX");
Wrapper.Register("user32.dll", "GetKeyState", "i=n", "f=s");
// Код клавиши CapsLock - 0x14 (20 в десятичной системе)
Результат = Wrapper.GetKeyState(20);
// Если младший бит равен 1, то CapsLock включен
Возврат (ЛогическоеИ(Результат, 1) <> 0);
Исключение
Возврат Ложь; // Если не удалось определить, считаем, что выключен
КонецПопытки;
КонецФункции
Этот метод позволяет выводить пользователю предупреждение «Внимание: включен CapsLock, сканирование может быть некорректным!» еще до начала работы.
В ситуациях с кодами маркировки Честный ЗНАК, когда мы точно знаем структуру кода (DataMatrix содержит определенные группы символов), можно применить алгоритм «интеллектуальной коррекции». Разберем этот алгоритм по шагам:
s (код 115) заменяем на S (код 83), если исходный код предполагал латиницу.Пример простейшей перекодировки (нормализации) для латиницы:
Функция НормализоватьШтрихкод(ИсходныйШК)
// Если мы определили, что регистр инвертирован
Результат = "";
Для Индекс = 1 По СтрДлина(ИсходныйШК) Цикл
Символ = Сред(ИсходныйШК, Индекс, 1);
КодСимвола = КодСимвола(Символ);
// Пример логики инверсии:
Если КодСимвола >= 65 И КодСимвола <= 90 Тогда // A-Z
Результат = Результат + НРег(Символ);
ИначеЕсли КодСимвола >= 97 И КодСимвола <= 122 Тогда // a-z
Результат = Результат + ВРег(Символ);
Иначе
Результат = Результат + Символ;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Проблема CapsLock при сканировании — это классический пример конфликта между эмуляцией пользовательского ввода и строгими требованиями к данным. Мы рассмотрели несколько путей решения: от наиболее правильного (переход на Native API / COM) до обходных путей с использованием Windows API или программной коррекции. Для работы с кодами маркировки настоятельно рекомендуем использовать именно первый способ, так как он гарантирует 100% точность передачи спецсимволов и идентификаторов применения GS1, на которые состояние клавиатуры влияет непредсказуемым образом.