При работе с торговым оборудованием, особенно со сканерами QR и DataMatrix кодов, программисты часто сталкиваются с проблемой «неправильного» регистра. Если сканер подключен в режиме эмуляции клавиатуры (keyboard wedge), а на компьютере пользователя случайно включен CapsLock, данные попадают в систему в инвертированном виде. Для кодов маркировки систем вроде «Честный ЗНАК» это критично: серийные номера и криптохвосты чувствительны к регистру, и любая ошибка делает код невалидным. Рассмотрим подробно, как программно определить состояние клавиши CapsLock и исправить ситуацию в среде 1С:Предприятие.
Разберем ситуацию: современная маркировка (например, для обуви, одежды или лекарств) использует двумерные штрихкоды формата DataMatrix. В отличие от простых линейных штрихкодов EAN-13, эти коды содержат в себе идентификаторы применения (AI), серийные номера и защитные последовательности, в которых латинские буквы могут быть как заглавными, так и строчными. Если сканер имитирует нажатие клавиш, то при включенном CapsLock буква a превращается в A, и наоборот.
Ситуация осложняется при работе через терминальный сервер (RDP). На 120 торговых точках устанавливать драйверы и настраивать каждый сканер как COM-устройство трудозатратно и часто нестабильно из-за качества каналов связи. Поэтому эмуляция клавиатуры остается самым популярным, хоть и «капризным» методом подключения. Выясним, как научить 1С самостоятельно проверять «враждебный» режим ввода.
Поскольку в штатном функционале платформы 1С отсутствуют методы для опроса состояния низкоуровневых клавиш клавиатуры, мы воспользуемся механизмом вызова функций Windows API. Самый надежный способ для обычных форм — использование библиотеки dynwrap.dll (DynamicWrapper), которая позволяет обращаться к системным функциям user32.dll.
Рассмотрим по шагам процесс настройки и написания кода:
dynwrap.dll. Если вы работаете в 64-битной операционной системе, файл необходимо скопировать в папку C:\Windows\SysWOW64. После этого запустите командную строку от имени администратора и выполните регистрацию: regsvr32 C:\Windows\SysWOW64\dynwrap.dll.GetKeyState.Проанализируем пример функции, которая проверяет состояние CapsLock и автоматически выключает его, если он активен:
Процедура ПроверитьИОтключитьКапсЛок()
Попытка
// Создаем объект для работы с WinAPI
Врап = Новый COMОбъект("DynamicWrapper");
// Регистрируем функцию GetKeyState из системной библиотеки USER32.DLL
// "i=l" означает входной параметр типа Long (код клавиши)
// "r=l" означает возвращаемое значение типа Long
Врап.Register("USER32.DLL", "GetKeyState", "i=l", "f=s", "r=l");
// Код клавиши CapsLock в Windows равен 20 (0x14)
Состояние = Врап.GetKeyState(20);
// Если младший бит равен 1, значит CapsLock включен
Если Состояние = 1 Тогда
// Используем стандартный Shell для эмуляции нажатия клавиши и выключения режима
WshShell = Новый COMОбъект("WScript.Shell");
WshShell.SendKeys("{CAPSLOCK}");
Сообщить("Внимание: CapsLock был автоматически выключен для корректного сканирования!");
КонецЕсли;
Исключение
// Если компонента не зарегистрирована, лучше оповестить администратора
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Оборудование.Сканер", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
КонецПопытки;
КонецПроцедуры
Если в вашей организации запрещено использование сторонних DLL, которые требуют регистрации (как dynwrap.dll), можно воспользоваться возможностями платформы .NET Framework, которая установлена практически на любом современном сервере Windows. Метод Control.IsKeyLocked позволяет получить состояние клавиш-переключателей без лишних сложностей.
Посмотрим на реализацию этого метода через COM-интерфейс:
Функция КапсЛокВключен() Экспорт
Попытка
// Используем .NET класс через динамическую обертку (если настроено взаимодействие)
// В типовых решениях это часто реализуется через внешние компоненты типа NetObjectTo1C
// Или прямое обращение к объектам через скриптовые языки
// Ниже приведен концептуальный пример:
Control = Новый COMОбъект("System.Windows.Forms.Control");
Возврат Control.IsKeyLocked(20); // 20 - Keys.Capital
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Рассмотрим ситуацию, когда у вас нет прав администратора для регистрации библиотек, а сканер все равно шлет данные в неправильном регистре. В этом случае мы можем применить алгоритм программной коррекции. Данный метод основан на анализе считанной строки кода DataMatrix.
Как мы выяснили, коды маркировки «Честный ЗНАК» содержат латиницу. Если мы заранее знаем, что в коде должны быть английские буквы, но получаем русские — значит, включена неверная раскладка. Если же буквы латинские, но их регистр кажется подозрительным (например, первая буква в поле, которое обычно строчное, пришла заглавной), мы можем выполнить инверсию.
Пример функции для инверсии регистра:
Функция ИнвертироватьРегистрСтроки(Знач ВходнаяСтрока)
Результат = "";
Для Поз = 1 По СтрДлина(ВходнаяСтрока) Цикл
Символ = Сред(ВходнаяСтрока, Поз, 1);
Если Символ = ВРег(Символ) Тогда
Результат = Результат + НРег(Символ);
Иначе
Результат = Результат + ВРег(Символ);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Важный нюанс: Этот метод следует применять с осторожностью. Проанализируем структуру кода DataMatrix: он часто содержит символы-разделители (GS, ASCII 29). При включенном CapsLock и определенных настройках драйвера эти непечатные символы могут искажаться. Поэтому самым надежным решением остается либо использование dynwrap.dll для принудительного выключения CapsLock перед началом ввода, либо перевод сканера в режим эмуляции COM-порта.
Выясним причину, по которой обычные методы иногда дают сбой в терминале. В среде RDP состояние клавиатуры (CapsLock, NumLock) синхронизируется между клиентом и сервером. Однако иногда возникает «залипание» или рассинхронизация. Если ваша процедура GetKeyState возвращает 0, а текст все равно вводится заглавными буквами, это может означать, что на стороне клиента зажат Shift.
Для решения таких проблем в высоконагруженных системах рекомендуется использовать специализированные внешние компоненты (ВК), которые перехватывают «сырой ввод» (Raw Input) от устройства, идентифицируя его именно как сканер, а не как клавиатуру. Это полностью исключает влияние регистра и раскладки на результат.
Для гарантированного результата на терминальном сервере рекомендуем:
GetKeyState(20) через dynwrap.dll для проверки CapsLock.WScript.Shell.SendKeys("{CAPSLOCK}").Соблюдение этих правил позволит избежать ошибок при работе с ГИС МТ (Честный ЗНАК) и существенно сократит количество звонков в службу технической поддержки от кассиров и кладовщиков.