2009-02-25 47 views
19

Tengo un escáner de código de barras (que funciona como un teclado) y, por supuesto, también tengo un teclado conectado a una computadora. El software acepta entradas tanto del escáner como del teclado. Necesito aceptar solo la entrada del escáner. El código está escrito en C#. ¿Hay alguna manera de "desactivar" la entrada desde el teclado y solo aceptar la entrada desde el escáner?Cómo distinguir entre múltiples dispositivos de entrada en C#

Nota: El teclado es parte de una computadora portátil ... por lo que no se puede desenchufar. Además, traté de poner el siguiente código protected override Boolean ProcessDialogKey (System.Windows.Forms.Keys keyData) { return true; } Pero además de ignorar las teclas del teclado, la entrada del escáner de código de barras también se ignora.

No puedo hacer que el escáner envíe caracteres de señal como, el escáner está siendo utilizado por otras aplicaciones y agregar una secuencia de caracteres sentinales significaría modificar otro código.

Además, no puedo usar el método de tiempo para determinar si la entrada vino de un escáner de código de barras (si es un grupo de caracteres seguido de una pausa) ya que los códigos de barras podrían ser códigos de barras de un solo personaje.

Sí, estoy leyendo datos de una transmisión.

Estoy tratando de seguir con el artículo: distinguir los escáneres de códigos de barras del teclado en WinForms. Sin embargo, tengo las siguientes preguntas:

  1. Me sale un error NativeMethods es inaccesible debido a su nivel de protección. Parece que necesito importar un dll; ¿es esto correcto? Si es así, ¿cómo lo hago?
  2. ¿Qué protección anula la definición de WndProc (ref Message m) que debo usar, hay dos implementaciones en el artículo?
  3. Aparece un error relacionado con [SecurityPermission (SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] error CS0246: No se puede encontrar el tipo o el nombre de espacio de nombres 'SecurityPermission' (¿falta una directiva using o una referencia de ensamblado?) ¿Cómo resuelvo este error?
  4. También hay un error en la línea que contiene: if ((desde hardwareId en hardwareIds donde deviceName.Contains (hardwareId) seleccione hardwareId) .Count()> 0) Error es el error CS1026:) expected.
  5. ¿Debo colocar todo el código en el artículo en un archivo .cs llamado BarcodeScannerListener.cs?

preguntas Followup sobre C# código fuente de solución publicado por Nicholas Piasecki en http://nicholas.piasecki.name/blog/2009/02/distinguishing-barcode-scanners-from-the-keyboard-in-winforms/:

  1. yo no era capaz de abrir la solución en VS 2005, lo que he descargado de Visual C# 2008 Express Edition, y el código corrió. Sin embargo, después de conectar mi escáner de código de barras y escanear un código de barras, el programa no reconoció el escaneo. Puse un punto de quiebre en el método OnBarcodeScanned pero nunca fue golpeado. Cambié el App.config con el ID de mi escáner de código de barras obtenido usando Device Manager. Parece haber 2 DeviceNames con HID # Vid_0536 & Pid_01c1 (que se obtiene del Administrador de dispositivos cuando el escáner está conectado). No sé si esto está causando que el escaneo no funcione. Al iterar sobre deviceNames, aquí está la lista de dispositivos que encontré (usando el depurador):

"\ ??\ 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}"

Por lo tanto, hay 2 entradas para HID # Vid_0536 & Pid_01c1; ¿Podría estar causando que el escaneo no funcione?

OK, así que parece que tuve que encontrar la manera de no depender del carácter ASCII 0x04 que envía el escáner ... ya que mi escáner no envía ese carácter. Después de eso, se dispara el evento escaneado con código de barras y se muestra la ventana emergente con el código de barras. Entonces, gracias a Nicholas por tu ayuda.

+0

Desconecte el teclado. – TheTXI

+0

Agregué una publicación de código de muestra en la parte inferior del artículo. ¡Buena suerte! –

+1

@NicholasPiasecki han pasado 6 años, pero aún así, ¿por qué HTTP 410? – itsho

Respuesta

15

You could use the Raw Input API to distinguish between the keyboard and the scanner like I did recently. No importa cuántos dispositivos con teclado o teclado haya conectado; verá un WM_INPUT antes de asignar la pulsación de tecla a una clave virtual independiente del dispositivo que normalmente se ve en un evento KeyDown.

Mucho más fácil es hacer lo que otros han recomendado y configurar el escáner para enviar los caracteres centinelas antes y después del código de barras. (Generalmente lo hace escaneando códigos de barras especiales en la parte posterior del manual del usuario del escáner.) Luego, el evento KeyPreview de su formulario principal puede ver los eventos clave para cualquier control secundario si está en el medio de una lectura de código de barras.O, si quieres ser más elegante, puedes usar un gancho de teclado de bajo nivel con SetWindowsHookEx() para mirar esos centinelas y tragarlos allí (la ventaja de esto es que aún podrías obtener el evento incluso si tu aplicación no tenía foco) .

No pude cambiar los valores de centinela en nuestros escáneres de códigos de barras, entre otras cosas, así que tuve que tomar la ruta complicada. Fue definitivamente doloroso. ¡Mantenlo simple si puedes!

-

su actualización, siete años más tarde: Si su caso de uso es la lectura de un escáner de código de barras USB, Windows 10 tiene un buen API, amigable para esta incorporada en Windows.Devices.PointOfService.BarcodeScanner. Es una API de UWP/WinRT, pero también puedes usarla desde una aplicación de escritorio común; eso es lo que estoy haciendo ahora. Aquí es un código de ejemplo para ello, directamente desde mi aplicación, para darle la esencia:

{ 
    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; 
      } 
     } 
    } 
} 

Por supuesto, se necesita un escáner de código de barras que es compatible con el USB HID POS y no es sólo una cuña de teclado. Si su escáner es solo una cuña de teclado, le recomiendo recoger algo así como una Honeywell 4600G usada de eBay por $ 25. Confía en mí, tu cordura valdrá la pena.

+0

Estoy intentando seguir el artículo. Sin embargo, me sale un error NativeMethods es inaccesible debido a su nivel de protección. Parece que necesito importar un dll; ¿es esto correcto? Si es así, ¿cómo lo hago? Además, ¿qué protección anulé la definición de WndProc (ref Message m) que debería usar? –

+1

También aparece un error relacionado con [SecurityPermission ( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] error CS0246: No se puede encontrar el tipo o el nombre de espacio de nombres 'SecurityPermission' (¿falta una directiva using o un ensamblado? referencia) –

+0

Junto con un error en la línea que contiene:? si ((de HardwareID en hardwareIds donde deviceName.Contains (HardwareID) \t \t \t seleccione HardwareID) .Count()> 0) error es CS1026 error:) esperado –

0

Depende de la forma en que interactúe con el dispositivo. De todos modos, no será una solución de C#, será alguna otra biblioteca. ¿Estás leyendo datos de una secuencia? Si solo está presionando teclas, puede que no haya nada que pueda hacer al respecto.

2

Lo que hice en una situación similar es distinguir entre un escaneo y un usuario escribiendo mirando la velocidad de la entrada.

Muchos caracteres muy juntos y una pausa es un escaneo. Cualquier otra cosa es la entrada del teclado.

No sé exactamente a sus necesidades, así que tal vez no lo hará por usted, pero es lo mejor que tengo :)

+0

Sí, encontrar y leer directamente desde el dispositivo no es trivial. Debería ser capaz de configurar el escáner para dar inicio y detener secuencias también - estas secuencias nunca ocurrirían en el teclado. –

+0

¿Puede proporcionar algún ejemplo de código sobre cómo lo logró? También encontré la solución usando la velocidad de entrada. Sin embargo, esta no es una buena opción. A veces, los márgenes entre las teclas son tan grandes. Por ejemplo: 15 15 16 180 13 15 15 15 (en milisegundos) –

-1

creo que podría ser capaz de distinguir varios teclados a través de la API DirectX , o si eso no funciona, a través de la API de entrada sin procesar.

+0

(nota: un escáner de código de barras aparece como otro teclado más en Windows) –

0

He logrado con éxito lo que ustedes buscan aquí. Tengo una aplicación que recibe todos los datos de caracteres del código de barras de un escáner de código de barras Honeywell/Metrologic. Ninguna otra aplicación en el sistema recibe los datos del escáner, y el teclado continúa funcionando normalmente.

Mi aplicación utiliza una combinación de entrada sin procesar y el temido sistema de enganche del teclado de bajo nivel. Contrariamente a lo que está escrito aquí, encontré que el mensaje wm_input se recibe antes de que se llame a la función hook del teclado. Mi código para procesar el mensaje wm_input básicamente establece una variable booleana para especificar si el carácter recibido proviene del escáner o no. La función de enlace del teclado, llamada inmediatamente después de que se procesa wm_input, traga los datos del pseudo-teclado del escáner, impidiendo que otras aplicaciones reciban los datos.

La función de enganche del teclado debe colocarse en una dll ya que desea interceptar todos los mensajes del teclado del sistema. Además, se debe usar un archivo mapeado en memoria para que el código de procesamiento wm_input se comunique con el dll.

+3

¿Quieres compartir algo del código con nosotros? –

+0

¿Algo nuevo en esto? - Parece que el chico ha estado publicando varios comentarios en diferentes páginas sobre este tema. – Mathias

-1

Sé que este es un hilo antiguo, lo encontré buscando el escaneo de código de barras en WIN10. Solo unas pocas notas en caso de que alguien lo necesite.

Estos escáneres de Honeywell tienen varias interfaces USB. Uno es un teclado + Hid Punto de venta (dispositivo compuesto). También hay CDC-ACM (emulación ComPort) y Hid Point of Sales (solo) + más.

De forma predeterminada, los escáneres exponen un número de serie, por lo que el host puede distinguir entre muchos dispositivos (una vez tuve conectado +20). Sin embargo, hay un comando para deshabilitar el número de serie.

Los modelos más nuevos se comportan igual en este sentido. Si quieres verlo en vivo, prueba mi programa de terminal yat3 (gratis en my site). Puede abrir todas las interfaces mencionadas anteriormente y está diseñado para tales dispositivos.

Una palabra para utilizar interfaces de teclado:
Úselos únicamente como último recurso. Son lentos, menos confiables cuando se trata de personajes exóticos. El único buen uso es si desea ingresar datos en aplicaciones existentes. Si codifica de todos modos, leer desde ComPort/HidPos-Device es más fácil.

Cuestiones relacionadas