2013-11-18 2 views
2

Я занимаюсь интеграцией поддержки USB-сканеров штрих-кодов в приложение WPF, но я попал в ловушку.Блокировка ввода с клавиатуры HID

В настоящее время я успешно идентифицирую и записываю ввод с помощью статьи this.

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

Я попробовал два метода захвата ввода: определение

var wndSourceHandle = HwndSource.FromHwnd(new WindowInteropHelper(
              _wndEventSource = value).Handle); 
wndSourceHandle.AddHook(this.WndProc); 

WndProc:

private IntPtr WndProc(IntPtr hwnd, int iMessage, IntPtr wParam, IntPtr lParam, ref bool bisHandled) 
    { 
     if (iMessage == Win32.WM_INPUT) 
     { 
      var result = ProcessRawInput(lParam); 
      bisHandled = result != null && result.Value; 
      return IntPtr.Zero; 
     } 

     return IntPtr.Zero; 
    } 

Как также:

ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) => 
       { 
        if (msg.message == Win32.WM_INPUT) 
        { 
         var result = ProcessRawInput(msg.lParam); 
         handled = result != null && result.Value; 
         return; 
        } 

        handled = false; 
       }; 

Метод ProcessRawInput возвращает истину, если источник вход - сканер штрих-кода, в противном случае - false.

ответ

2

После нескольких исследований я нашел решение, применимое к WinForms here. Я был в состоянии изменить его для WPF следующим образом:

ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) => 
       { 
        if (msg.message == Win32.WM_INPUT) 
        { 
         var result = ProcessRawInput(msg.lParam); 
         this.m_bIgnoreNextKeyDownMessage = result != null && result.Value; 
         return; 
        } 
        if (msg.message == Win32.WM_KEYDOWN && this.m_bIgnoreNextKeyDownMessage) 
        { 
         handled = true; 
        } 

        this.m_bIgnoreNextKeyDownMessage = false; 
       }; 

Этого решение в основном знаменует собой первое сообщение WM_KEYDOWN после штрихкода WM_INPUT сообщений как «обработано». Я не уверен, что это единственное/лучшее/безопасное решение, но похоже, что это трюк.

Update:

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

if (msg.message == Win32.WM_KEYDOWN && !String.IsNullOrEmpty(this.m_strKeyInput)) 
{ 
    handled = true; 
} 

Буфер m_strKeyInput содержит текущее отсканированное значение штрих-кода - это буфер пуст, когда нет штрих-код не доступен, построенный на один символ в то время как сканер штрих-кодов выталкивает штрих-код, а затем очищается, когда генерируется пользовательское событие BarcodeScanned. Единственным недостатком этого решения, о котором я могу думать, является то, что все клавиатуры перестанут функционировать в течение нескольких миллисекунд, из которых штрихкод выталкивается из сканера, что приемлемо для моего сценария.

+0

Работает ли приложение, когда программа сведена к минимуму? - так что, если вы сканируете на рабочем столе, вы приложение поймаете данные? – Mathias

+0

Я протестировал и поймал данные штрих-кода, даже если программа сведена к минимуму. Для моих требований это не проблема. – RiaanDP

0

Похоже на то, что вы отправляете вход со сканера (рассматривая его как клавиатуру), и в текстовое поле вы можете просто использовать один из событий Preview * в этом текстовом поле для выполнения дополнительной обработки. Например, вы можете переопределить PreviewTextInput

private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) 
{ 
    // MyBarcodeScanner would be a reference to the IInput device that represents the scanner: 
    if (e.Device == MyBarcodeScanner) 
    { 
    // Process the text, rejecting it in this case. 
    // Marking the event as handled will prevent the 'TextChanged' event 
    // from firing, so the characters will not appear in the text box. 
    e.Handled = true; 
    } 
    else 
    { 
    // This is some other keyboard, by not handling the event, 
    // the users will be allowed to enter text normally. 
    } 
} 

Вы, возможно, придется сделать несколько проб и ошибок, чтобы выяснить, как идентифицировать сканер штрих-кода, который идентифицируется «e.Device», но это должно быть относительно легко. Извините, я не могу быть более полным, но у меня нет собственного сканера штрихового кода, чтобы экспериментировать.

+0

Вход со сканера обрабатывается фоновым потоком - я пытаюсь предотвратить ввод ввода с устройства сканера в любом сфокусированном текстовом поле в приложении при выполнении сканирования. – RiaanDP

+0

Затем используйте одно и то же событие для предотвращения ввода. см. обновленный ответ. –

Смежные вопросы