Блокировка ввода с клавиатуры 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.
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