Introduction
The vast majority of bar code scanners emulate keyboards which allows them to be easily used in any application. The user simply needs to put the focus on any text input
control and then scan a bar code.
This same behaviour though also allows the user to scan bar codes into fields not intended for scanning, and does not allow the application
to take instant action when a scan is received because the application has no way of distinguishing the bar code scanner input from the keyboard.
Many vendors have their own APIs which can be used to distinguish the bar code scanner from the keyboard, but in the real world, there are thousands of bar code scanners
and relying on vendor specific APIs is not practical.
Fortunately, there is an easy yet not well known method for detecting distinct input from the bar code scanner. This allows the user to scan bar codes without needing
to put the focus on a special field, or activate buttons or menu items before each scan.
Background
One of my projects requires integration with POS peripherals for sales, receiving, inventory, and other standard retail functions. Recently we needed to integrate bar code readers.
Previously we had used them for lookups, serial number entry, etc. But users were required to tell the software first by clicking a button, or selecting a text box first
and then scanning the code. The software didn't know the difference between the scanner and the keyboard, and just took the text sent to it.
This approach allows for a lot of user mistakes, and is also inefficient. There are ways to directly integrate with bar code scanners using third party libraries, SDKs, or OPOS.
This seemed like a lot of fuss just to be able to get data from the bar code scanner.
Many people suggested OPOS and we already use OPOS for interacting with high speed thermal printers. OPOS however relies on individual setup on each machine,
and a separate OPOS driver for each piece of hardware. Vendor support for OPOS is varied, and often shoddy. For the printers, we accept this because it provides
significant benefits over interacting with the raw printer interface and thermal printers tend to be higher end devices with well established OPOS drivers.
Bar code scanners however are lower cost items and we may have many different brands.
I did more searching and found that many users resorted to use the WinAPI and keyboard hooks. Most of these solutions required a lot of external calls and many relied on Windows messages
which did not work as well with WPF. They also required the developer to uniquely identify they device specifically on each machine.
My First Try
Bar code scanners can be programmed to send a prefix and suffix for each scan, typically STX (start of text) and ETX (end of text). They are 0x02 and 0x03 in ASCII, respectively.
I created a KeyDown event in a WPF app and scanned a bar code. The first key I received was LeftCtrl. LeftCtrl??? Obviously WPF didn't know how to handle low ASCII codes
that keyboards were never designed to send. WPF deals with scan codes anyway, and not all ASCII codes can map to scan codes.
I gave up this approach and tried many of the fairly complex WinAPI approaches to try to access the raw input from the bar code scanner. Most had problems with WPF
and required a lot of adaptation because they were written for WinForms and relied on Windows messages. I got one to work relatively easily and became excited.
But then I ran my first test and got a code of 162. 162 is the scan code for LeftCtrl. :(
Retry
Back to WPF and a simple PreviewKeyUp. I decided to dig a bit deeper past the first character and realized that there was a bit of a pattern.
I hoped that I could detect this pattern reliably and intercept the keystrokes. I made a program to log key ups and downs and realized quickly that STX (0x02) was being translated to:
- LeftCtrl Down
- B Down
- B Up
- LeftCtrl Up
Then it hit me. My previous assumptions were wrong. Windows was seeing the 0x02. I previously had assumed Windows was getting confused, but in fact it was doing
a bit of translation. In the very old days of ASCII, Ctrl + a letter was mapped to 1-26 in ASCII. That is Ctrl-A was equivalent to 0x01. On many pre PC machines, you
could press Ctrl-M and the computer would see it the same as Enter (0x0D). So Windows was seeing the 0x02 from the bar code scanner and translating it to a series
of key code scans that represented Ctrl-B.
Now I had something I could work with.
The Code
I added two events to my main window: PreviewKeyUp and PreviewKeyDown. I kept track of the Ctrl key state and then looked for a B to detect Ctrl-B.
From there I collected all input until I found a Ctrl-C (ETX, 0x03) sequence. Note that most bar code readers do not send these sequences by default,
but nearly all can be easily reconfigured to do so.
From the Ctrl-B to the Ctrl-C, I assumed all input was from the bar code scanner and set the event handled property so other events in my program would not see the data.
At the end, I called an event and handed the data off to my program.
Demo
In the demo, the sole purpose of the edit field is to show that normal keyboard input is taken, but bar code scanner input is not.
The listbox on the left shows the raw key scan sequences, and each bar code result is added to the listbox on the right.
The demo was built in C#, WPF, and Visual Studio 2010. It can be very easily used with VB.NET, WinForms, and other versions of Visual Studio.

Reuse
This method can be easily encapsulated into a class for easy reuse on any window. In my application, all of our WPF windows descend from a common base class,
so I have put the functionality there. For each window, I simply need to add this in the constructor:
ScanReceived = Scan;
void Scan(string aData) {
MessageBox.Show("Scan received: " + aData);
}
Result
Without the use of WinAPI, invasive code, or complex code, I found a method to reliably interpret bar code scanner input. In fact the actual code fits easily on a screen.
With this method, you also do not need to identify to the code which device is the bar code scanner. The code simply looks for patterns in the key presses and separates the data out.
Caveat
There is one small caveat. Ctrl-B cannot be used in your application for menus or other hot key functions. The code relies on this to detect the start of input from the bar code scanner.
The code also looks for Ctrl-C, but only after a Ctrl-B. At other times, it ignores Ctrl-C, so the commonly used shortcut for copy to clipboard does not conflict with usage of this code.
Known Issues
There are a few issues when other keypress handlers exist on the window. I have addressed these in my production code and will update the demo as time permits.
Alternate Method - Keyboard Detection
Recently I have been thinking of changing the detection to look at which keyboard instance the keys come from. Since the bar code readers register as a keyboard, instead of looking for a prefix the name of the keyboard instance could be used instead. This method will also work with magnetic stripe readers and allow use of bar code scanners without the need to program them to use a prefix or suffix.
Future Expansion
Bar code scanners can also be programmed to issue other prefixes to identify the type of code scanned, i.e., UPC vs. Code39. With the products we deal with, this is useful
because if a UPC is scanned we know it identifies the product, while Code39 and other non UPC/EAN codes typically represent serial numbers of the item. This allows users
to receive items very quickly without the need to identify first what they want to do to the software, and instead the software can infer the user intended actions based
on the active window. I have expanded my code to recognize other prefixes and respond with other available events. At some point I will merge my updated code back into this example.