Блокировка ввода с клавиатуры HID



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



В настоящее время я успешно идентифицирую и фиксирую входные данные с помощью этой статьи.



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



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



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 возвращает true, если источником входных данных является сканер штрих-кодов, в противном случае false.

642   2  

2 ответов:

После еще нескольких исследований я нашел решение, применимое к WinForms здесь. Я смог изменить его для 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 как "обработанное". Я не уверен, что это единственное / лучшее / безопасное решение, но похоже, что оно делает трюк.

Обновление:

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

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

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

Похоже, что, поскольку вы направляете ввод со сканера (рассматривая его как клавиатуру) в текстовое поле, вы можете просто использовать одно из событий 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", но это должно быть относительно легко. Извините, я не могу быть более полным, но У меня нет собственного сканера штрих-кодов для экспериментов.

Comments

    Ничего не найдено.