2013-11-12 4 views
0

Я использую глобальный клавиатурный крючок для работы со считывателем штрих-кода. Считыватель штрих-кода отправляет символ STX перед штрих-кодом и символ ETX после штрих-кода.GetKeyboardState и ToAscii не всегда правильно обрабатывают символы STX и ETX.

Иногда функция ToAscii приводит к соответствующим кодам STX и ETX (0x02 или 0x03), но большую часть времени она становится 0x62 (b) или 0x63 (c).

Можно ли это объяснить и разрешить?

Я добавил крючок обратного вызова для ясности ниже:

private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) 
    { 
     if (nCode >= 0) 
     { 
      // Prepare the characters and retrieve the keyboard state. 
      char[] characters = new char[2]; 
      byte[] keyState = GetKeyboardState(); 


      if (KeyPressed != null && WinAPI.ToAscii(lParam.vkCode, lParam.scanCode, keyState, characters, 0) == 1) 
      { 
       // Initialize the event arguments and fire the KeyPressed event. 
       GlobalKeyboardHookEventArgs e = new GlobalKeyboardHookEventArgs(characters, (int)wParam); 
       KeyPressed(null, e); 

       // Do not call the next hook if the event has been handled. 
       if (e.Handled) 
       { 
        return (IntPtr)1; 
       } 
      } 
     } 

     // Call the next hook. 
     return WinAPI.CallNextHookEx(hook, nCode, wParam, ref lParam); 
    } 
} 
+0

Есть много причин думать ... Пожалуйста, разместите код, чтобы мы могли понять суть контекста. – lboshuizen

+0

Я добавил код обратного вызова. – saracaen

+0

STX и ETX - это общие управляющие коды, используемые при передаче по последовательному порту. Они не имеют смысла для клавиатуры, и вы никогда не должны передавать их ToAscii(). –

ответ

1

Поскольку сканер и должен быть настроен в качестве USB-клавиатуры, я вынужден захватить вход, используя крюк клавиатуры низкого уровня. Однако вместо того, чтобы использовать символы STX/ETX в качестве префикса/суффикса, я теперь настроил сканер для отправки команды клавиатуры (Alt + Shift + Backspace) в качестве префикса и суффикса.

Это позволяет мне определить, когда появится штрих-код и когда он закончит. Чтобы предотвратить случайное (или преднамеренное) использование пользователем команды клавиатуры, я использовал таймер. Таймер гарантирует, что разбор штрих-кода отменяется, если после 100 миллисекунд не будет получен штрих-код.

Команда клавиатуры поймана с помощью вызовов RegisterHotKey и UnregisterHotKey Windows API.

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

+0

Мудрый решение. У вас есть мои голоса :-) – lboshuizen

0

сканера действует как клавиатуры, но это не так.

При вызове окна WinApi.ToAscii() переводится ввод в «действительную» комбинацию клавиш. ToAscii() интерпретирует 0x02 как ключ, отображаемый на 'b'. Но это будет зависеть от текущей активной установленной/настроенной клавиатуры. Так что просто полагаясь на «b» & «c» может вызвать проблемы на ... Русская клавиатура :-)

Просто используйте исходные входные данные, извлеките данные между STX/ETX и нарисуйте эту часть в Ascii. Этот код ключа должен быть в lParam.vkCode или lParam.scanCode. KBDLLHOOKSTRUCT

Результат может пролетели как в следующем, но я не могу проверить это прямо сейчас

private bool _isScanningCode; 

private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam) 
    { 
     if (nCode >= 0) 
     { 
      // Prepare the characters and retrieve the keyboard state. 
      char[] characters = new char[2]; 
      byte[] keyState = GetKeyboardState(); 

      if (lParam.scanCode == 0x02) 
      { 
       _isScanningCode == true; 
       return (IntPtr)1; // act like key is handled 
      } 
      if (lParam.scanCode == 0x03) 
      { 
       _isScanningCode == false; 
       return (IntPtr)1; //act like key is handled 
      } 

      if (_isScanningCode) 
      { 

       if (KeyPressed != null && 
        WinAPI.ToAscii(lParam.vkCode, lParam.scanCode, keyState, characters, 0) == 1) 
       { 
        // Initialize the event arguments and fire the KeyPressed event. 
        GlobalKeyboardHookEventArgs e = new GlobalKeyboardHookEventArgs(characters, (int) wParam); 
        KeyPressed(null, e); 

        // Do not call the next hook if the event has been handled. 
        if (e.Handled) 
        { 
         return (IntPtr) 1; 
        } 
       } 
      } 
     } 

     // Call the next hook. 
     return WinAPI.CallNextHookEx(hook, nCode, wParam, ref lParam); 
    } 
} 
+0

Хотя сырые входные данные будут работать, это не позволит мне проглотить вход сканера, чтобы предотвратить его использование в другом месте. Кроме того, я не понимаю, как это возможно, что он может работать и не работать, казалось бы, случайно на одном ПК. – saracaen

+0

Я боюсь, что подход, который вы предлагаете, не работает. 0x02 или 0x03 никогда не помещаются непосредственно в код сканирования или код виртуального ключа. – saracaen

+0

Любые другие предложения? – saracaen