Как отличить несколько устройств ввода в C # - PullRequest
21 голосов
/ 26 февраля 2009

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

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

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

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

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

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

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

Последующие вопросы об исходном коде решения 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 & 0 & 0000 # {4d1e55b2-F16F-11cf-88cb-001111000030}" * * тысяча тридцать-два

"\ ?? \ HID # Vid_0536 & Pid_01c1 & MI_00 # 9 & 38e10b9 & 0 & 0000 # {884b96c3-56ef-11d1-bc8c-00a0c91405dd}" * +1034 * * 1 035 * "\ ?? \ HID # Vid_413c & Pid_2101 & MI_00 # 8 & 1966e83d & 0 & 0000 # {884b96c3-56ef-11d1-bc8c-00a0c91405dd}"

* * Тысяча тридцать-семь "\ ?? \ HID # Vid_413c & Pid_3012 # 7 & 960fae0 & 0 & 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, отправляемого сканером ... так как мой сканер не отправляет этот символ. После этого запускается событие сканирования штрих-кода и отображается всплывающее окно со штрих-кодом. Так что спасибо Николас за вашу помощь.

Ответы [ 7 ]

17 голосов
/ 26 февраля 2009

Вы можете использовать Raw Input API, чтобы различать клавиатуру и сканер, как я это делал недавно. Не имеет значения, сколько клавиатур или подобных им устройств вы подключили; вы увидите WM_INPUT до того, как нажатие клавиши будет сопоставлено с независимым от устройства виртуальным ключом, который вы обычно видите в событии KeyDown.

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

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

-

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

{
    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 долларов. Поверь мне, твое здравомыслие того стоит.

3 голосов
/ 26 февраля 2009

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

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

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

1 голос
/ 29 октября 2015

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

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

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

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

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

1 голос
/ 15 мая 2013

посмотрите на это: http://nate.dynalias.net/dev/keyboardredirector.rails ( НЕ ДОСТУПНО БОЛЬШЕ ) отлично работает!

Укажите клавиатуру и клавиши, которые вы хотите заблокировать, и она работает как шарм!

Также взгляните на это: http://www.oblita.com/interception.html Вы можете создать для него оболочку C # - она ​​также работает как шарм ..

1 голос
/ 26 февраля 2009

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

0 голосов
/ 01 сентября 2011

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

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

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

0 голосов
/ 26 февраля 2009

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

...