Brothers In Code

...a serious misallocation of .net resources

Event-Based Keyboard Wedge Scanner

I just came off a project programming Motorola barcode canners based on Windows Mobile.  The Motorola/Symbol API was top notch and provided access to everything I needed.  This included an event driven API for the scanner.  This meant I had a nice "Scan" event to use from within my code rather than rely on simple keyboard emulation.  This great when a single barcode had multiple fields of data.  I could parse everything behind the scenes without using a "capture" field on my forms.

The next project also needed a barcode scanner but would be a Winforms app rather than a mobile app.  To my surprise the APIs for these usb and serial scanners were not nearly as good.  Only a select few scanners supported Motorola's usb SNAPI interface, and there was no native .net support there (just a bunch of DllImports).  Others had an RS232 based interface but it wasn't much better than reading raw data from the serial port.  A few of the scanners supported the OPOS standard which means I could have used POS for .net but that seemed overkill for my needs.

Finally I realized there was a much simpler solution.  Most of these scanners supported a keyboard emulation mode.  More importantly they supported the ability to be programmed to include prefixes and suffixes in the scan.  While most would use this feature to send an 'Enter' after a successful scan, I realized I could use this to send special characters to indicate the start and end of a scan and separate it from normal keyboard input.  From there making my own API was simple.

There were two main points to this.  The first was to monitor keypresses:

HostForm.KeyPreview = true;
this.enabled = true;
if (this.enabled)
{
  HostForm.KeyPress += new KeyPressEventHandler(KeyPressHandler);
}
else
{
  HostForm.KeyPress -= KeyPressHandler;
}

The line of interest here should be the Form.KeyPreview=true.  This allows you to pickup keyboard strokes at the form level rather than from the control with focus.

From there it's just a matter of looking for the started and ending characters (i chose ctrl-s and ctrl-t, ascii char 19 and 20 resp):

public void KeyPressHandler(object sender, KeyPressEventArgs e)
{
  //if a scan has started...
  if (!IsScanning && e.KeyChar == ScanStartCharacter)
  {
    IsScanning = true;
    timeoutTimer.Start();
    e.Handled = true;
    OnScanStarted();
  }
  //if a scan is in progress and is not being terminated...
  else if (IsScanning && e.KeyChar != ScanEndCharacter)
  {
    timeoutTimer.Stop();
    //...then add the char to the buffer
    scanBuffer.Append(e.KeyChar);

    timeoutTimer.Start();
    e.Handled = true;
  }
  //if a scan has ended
  else if (e.KeyChar == ScanEndCharacter)
  {
    timeoutTimer.Stop();

    CompleteScan(false);

    e.Handled = true;
  }
  else  //not scanning, pass the character on as keyboard input.
  {
    e.Handled = false;
  }
}

I threw a timer in there just to make sure the scan eventually completes, even if the user forgets to program the suffix into the scanner.

That's pretty much it.  The full code is attached.

Loading