2009-02-25 2 views
19

У меня есть сканер штрих-кода (который действует как клавиатура), и, конечно, у меня есть клавиатура, подключенная к компьютеру. Программное обеспечение принимает вход как от сканера, так и от клавиатуры. Мне нужно принять только вход сканера. Код написан на C#. Есть ли способ «отключить» ввод с клавиатуры и принимать только вход от сканера?Как отличить несколько устройств ввода в C#

Примечание: Клавиатура является частью ноутбука ... поэтому ее нельзя отключить. Кроме того, я попытался поставить следующий код protected override Boolean ProcessDialogKey (System.Windows.Forms.Keys keyData) { return true; } Но затем, игнорируя нажатия клавиш с клавиатуры, вход сканера штрих-кода также игнорируется.

Невозможно, чтобы сканер отправил ссылочные символы, так как сканер используется другими приложениями, а добавление потока сигнальных символов будет означать изменение другого кода.

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

Да, я читаю данные из потока.

Я стараюсь следовать вместе со статьей: Отличительные сканеры штрих-кода от клавиатуры в WinForms. Однако у меня есть следующие вопросы:

  1. Я получаю сообщение об ошибке NativeMethods недоступен из-за его уровня защиты. Кажется, мне нужно импортировать dll; это верно? Если да, то как мне это сделать?
  2. Какое защищенное определение woid WndProc (ref Message m) следует использовать, есть две реализации в статье?
  3. Получение ошибки, связанной с [SecurityPermission (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] error CS0246: Не удалось найти имя типа или пространства имен «SecurityPermission» (вам не хватает директивы using или ссылки на сборку?). Как устранить эту ошибку?
  4. Также есть ошибка в строке, содержащей: if ((from hardwareId в hardwareIds, где deviceName.Contains (hardwareId) select hardwareId) .Count()> 0) Ошибка - это ошибка CS1026:).
  5. Должен ли я размещать весь код в статье в одном файле .cs с именем BarcodeScannerListener.cs?

Followup вопросы о C# исходного раствора кода разместил Николас Пясецкий на http://nicholas.piasecki.name/blog/2009/02/distinguishing-barcode-scanners-from-the-keyboard-in-winforms/:

  1. я не смог открыть решение в VS 2005, так что я скачал Visual C# 2008 Express Edition, и код побежал. Однако после подключения сканера штрих-кодов и сканирования штрих-кода программа не распознала сканирование. Я поставил точку останова в методе OnBarcodeScanned, но он никогда не попадал. Я изменил App.config с идентификатором моего сканера штрих-кода, полученного с помощью диспетчера устройств. Кажется, есть 2 имени устройства с HID # Vid_0536 & Pid_01c1 (который получен из диспетчера устройств при подключении сканера). Я не знаю, вызывает ли это сканирование, чтобы он не работал. При итерации над именами устройств, вот список устройств, которые я нашел (используя отладчик):

"\ ??\ HID # Vid_0536 & Pid_01c1 & MI_01 # 9 & 25ca5370 0000 # {4d1e55b2-F16F-11cf-88cb-001111000030} "

" \ ?? \ HID # Vid_0536 & Pid_01c1 & MI_00 # 9 & 38e10b9 0000 # {884b96c3-56ef-11d1-bc8c-00a0c91405dd} "

" \ ?? \ HID # Vid_413c & Pid_2101 & MI_00 # 8 & 1966e83d 0000 # {884b96c3-56ef-11d1-bc8c- 00a0c914 05dd} "

"\ ?? \ HID # Vid_413c & Pid_3012 # 7 & 960fae0 0000 # {378de44c-56ef-11d1-bc8c-00a0c91405dd}"
" \ ?? \ Root # RDP_KBD # 0000 # {884b96c3-56ef-11d1-bc8c-00a0c91405dd} " "\ ?? \ ACPI # PNP0303 # 4 & 2f94427b & 0 # {884b96c3-56ef-11d1-bc8c-00a0c91405dd}" " \ ?? \ Root # RDP_MOU # 0000 # {378de44c-56ef-11d1-bc8c-00a0c91405dd}» "\ ?? \ ACPI # PNP0F13 # 4 & 2f94427b & 0 # {378de44c-56ef-11d1-bc8c-00a0c91405dd}"

Итак, есть 2 записи для HID # Vid_0536 & Pid_01c1; может ли это заставить сканирование работать?

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

+0

Отключите клавиатуру. – TheTXI

+0

Я добавил образец кода в нижней части статьи. Удачи! –

+1

@NicholasPiasecki прошло 6 лет, но все же - почему HTTP 410? – itsho

ответ

15

You could use the Raw Input API to distinguish between the keyboard and the scanner like I did recently. Не имеет значения, сколько клавиатурных или клавиатурных устройств вы подключили; вы увидите WM_INPUT перед нажатием клавиши на виртуальный ключ, не зависящий от устройства, который вы обычно видите в событии KeyDown.

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

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

-

Ваше обновление, семь лет спустя: Если Прецедент читает со сканера штрих-кода USB, Windows 10 имеет приятный, дружественный интерфейс для этого встроенный в Windows.Devices.PointOfService.BarcodeScanner. Это UWP/WinRT API, но вы также можете использовать его из обычного настольного приложения; вот что я сейчас делаю. Вот пример кода для этого, прямо из моего приложения, чтобы дать вам суть:

{ 
    using System; 
    using System.Linq; 
    using System.Threading.Tasks; 
    using System.Windows; 
    using Windows.Devices.Enumeration; 
    using Windows.Devices.PointOfService; 
    using Windows.Storage.Streams; 
    using PosBarcodeScanner = Windows.Devices.PointOfService.BarcodeScanner; 

    public class BarcodeScanner : IBarcodeScanner, IDisposable 
    { 
     private ClaimedBarcodeScanner scanner; 

     public event EventHandler<BarcodeScannedEventArgs> BarcodeScanned; 

     ~BarcodeScanner() 
     { 
      this.Dispose(false); 
     } 

     public bool Exists 
     { 
      get 
      { 
       return this.scanner != null; 
      } 
     } 

     public void Dispose() 
     { 
      this.Dispose(true); 
      GC.SuppressFinalize(this); 
     } 

     public async Task StartAsync() 
     { 
      if (this.scanner == null) 
      { 
       var collection = await DeviceInformation.FindAllAsync(PosBarcodeScanner.GetDeviceSelector()); 
       if (collection != null && collection.Count > 0) 
       { 
        var identity = collection.First().Id; 
        var device = await PosBarcodeScanner.FromIdAsync(identity); 
        if (device != null) 
        { 
         this.scanner = await device.ClaimScannerAsync(); 
         if (this.scanner != null) 
         { 
          this.scanner.IsDecodeDataEnabled = true; 
          this.scanner.ReleaseDeviceRequested += WhenScannerReleaseDeviceRequested; 
          this.scanner.DataReceived += WhenScannerDataReceived; 

          await this.scanner.EnableAsync(); 
         } 
        } 
       } 
      } 
     } 

     private void WhenScannerDataReceived(object sender, BarcodeScannerDataReceivedEventArgs args) 
     { 
      var data = args.Report.ScanDataLabel; 

      using (var reader = DataReader.FromBuffer(data)) 
      { 
       var text = reader.ReadString(data.Length); 
       var bsea = new BarcodeScannedEventArgs(text); 
       this.BarcodeScanned?.Invoke(this, bsea); 
      } 
     } 

     private void WhenScannerReleaseDeviceRequested(object sender, ClaimedBarcodeScanner args) 
     { 
      args.RetainDevice(); 
     } 

     private void Dispose(bool disposing) 
     { 
      if (disposing) 
      { 
       this.scanner = null; 
      } 
     } 
    } 
} 

Конечно, вам нужен сканер штрих-кодов, которые поддерживают USB HID POS и это не просто клин клавиатуры. Если ваш сканер - это просто клавиатурный клин, я рекомендую собрать что-то вроде используемого Honeywell 4600G с eBay за $ 25. Поверьте мне, ваше здравомыслие будет стоить того.

+0

Я пытаюсь следовать вместе со статьей. Однако я получаю сообщение об ошибке. NativeMethods недоступен из-за его уровня защиты. Кажется, мне нужно импортировать dll; это верно? Если да, то как мне это сделать? Кроме того, какое защищенное переопределение void WndProc (ref Message m) должно использоваться? –

+1

Также возникает ошибка, связанная с [SecurityPermission ( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] ошибка CS0246: Не удалось найти имя типа или пространства имен «SecurityPermission» (вам не хватает директивы использования или сборки ссылка) –

+0

Наряду с ошибкой на линии, содержащей: , если ((от HardwareID в hardwareIds , где deviceName.Contains (HardwareID) \t \t \t выберите HardwareID) .Count()> 0) ошибка ошибка CS1026:) Ожидаемый –

0

Это зависит от того, как вы взаимодействуете с устройством. В любом случае это не будет C# решение, это будет какая-то другая библиотека. Вы читаете данные из потока? Если вы просто выполняете нажатия клавиш, вы можете ничего не сделать с этим.

2

То, что я делал в подобной ситуации, - это различие между сканированием и пользовательским вводом, если смотреть на скорость ввода.

Множество символов очень близко друг к другу, а затем пауза - это сканирование. Все остальное - ввод с клавиатуры.

Я не знаю точно, ваши требования, так что, возможно, что не будет делать для вас, но это лучшее, что я получил :)

+0

Да, поиск и чтение с устройства напрямую нетривиальны. Вы должны быть в состоянии установить сканер, чтобы дать возможность запуска и остановки последовательно - эти последовательности никогда не будут возникать на клавиатуре. –

+0

Можете ли вы привести пример кода о том, как вы это достигли? Я также нашел решение, используя скорость ввода. Однако это нехорошие варианты. Иногда поля между нажатиями клавиш настолько велики. Например: 15 15 16 180 13 15 15 15 (в миллисекундах) –

-1

Я думаю, что вы могли бы быть в состоянии различить несколько клавиатур через DirectX API , или если это не сработает, через API исходных входных данных.

+0

(примечание: сканер штрих-кода выглядит как еще одна клавиатура для Windows) – 2009-02-25 23:25:23

0

Я успешно выполнил то, что вы ищете здесь. У меня есть приложение, которое получает все персональные данные штрих-кода от сканера штрих-кода Honeywell/Metrologic. Никакое другое приложение в системе не получает данные от сканера, и клавиатура продолжает нормально функционировать.

В моем приложении используется комбинация сырого ввода и страшной низкоуровневой клавиатуры. В отличие от того, что написано здесь, я обнаружил, что сообщение wm_input получено до вызова функции hook hook. Мой код для обработки сообщения wm_input в основном устанавливает логическую переменную, чтобы указать, является ли полученный символ из сканера. Функция перехвата клавиатуры, вызываемая сразу после обработки wm_input, проглатывает данные псевдо-клавиатуры сканера, предотвращая прием данных другими приложениями.

Функция перехвата клавиатуры должна быть помещена в dll, так как вы хотите перехватить все сообщения системной клавиатуры. Кроме того, файл с отображением памяти должен использоваться для кода обработки wm_input для связи с dll.

+3

Не забудьте поделиться с нами некоторым кодом? –

+0

что-нибудь новое на этом? - похоже, что парень опубликовал несколько комментариев на разных страницах по этой проблеме. – Mathias

-1

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

Эти сканеры от Honeywell имеют несколько интерфейсов USB. Один из них - клавиатура + Скрытая точка продаж (композитное устройство). Также есть CDC-ACM (эмуляция ComPort) и HID Point of sales (отдельно) + больше.

По умолчанию сканеры выставляют серийный номер, поэтому хост может различать многие устройства (я имел один раз +20 подключений). Есть команда отключить серийный номер, хотя!

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

Слово для использования интерфейсов клавиатуры:
Используйте их только в качестве последнего средства. Они медленные, менее надежные, когда дело доходит до экзотических персонажей. Единственное удобное использование - если вы хотите вводить данные в существующие приложения. Если вы все равно кодируете, то проще читать с ComPort/HidPos-Device.

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