views:

657

answers:

5

I recently acquired a Metrologic Barcode scanner (USB port), as everyone already knows it works as a keyboard emulator out of the box.

How do I configure the scanner and my application so that my app can process the barcode data directly? That is, I don't want the user to focus on a "Text field" and then process the data when the KeyPress event fires.

+1  A: 

I would guess the easiest way to do this would be to intercept key-presses at a higher level, such as PreviewKeyDown in winforms (or use KeyDown on the form, set KeyPreview to true, and use e.SuppressKeyPress to stop the key going down to the controls). There might be a direct API to the device; there might not.

Marc Gravell
+5  A: 

Usually barcode scanners can be configured to send some characters before and after the string. So if you append eg "F12" before the barcode string, you can capture that and move the focus to the right field.

Check the barcode scanner manual how to do that.

Harriv
Usually you *want* to have a text field anyway, so that users can manually enter the barcode if the scanning fails. That's why I think this is the best choice.
Dean Harding
This is how we do it with cheque readers; whether they are keyboard wedge or USB, we configure them to send a start character sequence that isn't easily typed at the keyboard. When we see that sequence via the form's keydown method, we swallow those special keypresses and move the input focus to the desired edit box. Works pretty well.
robsoft
A: 

If you can get away with Marc Grawell's solution, then by all means use that because anything else is going to be much more complicated. If that solution doesn't work (for example because the form contains other edit boxes where the user might actually want to input something) then read on...

  1. Take out the big book that came with your scanner, or download one from the INTERNET. Those devices usually have LOTS of configuration options, look for an option that allows you to set an "PREFIX" char or string and maybe even an "SUFIX". When an bar code is scanned, those codes would get set before the actual scan data and if you also get an sufix, after the scan data. From your form's KeyPreview events look for the prefix and only eat chars after you see the prefix. Even if there's no way to configure your own prefix, the scanner might send one any way, check it out.
  2. Maybe your "HID Keyboard" scanner also works in "serial emulation". Again, look for a configuration option. When I had to work with an bar code scanner I specifically requested an SERIAL scanner so I don't have any trouble differentiating between the real Keyboard and the Scanner.
  3. If everything else fails you might want to venture into the RawInput HID area. Look here: http://msdn.microsoft.com/en-us/library/ms645543(v=VS.85).aspx . At a minimum, using RawInput, you'd be able to diferentiate between chars that come from the real Keyboard and those that come from the barcode scanner, but I'm pretty sure you can't stop the messages from the BarCode scanner from making there own separate way back to your application...
Cosmin Prund
A: 

You can use the OnShortcut event on a form to intercept keyboard presses. Check if the prefix you configured on the barcodescanner appears, and set as Handled al keypresses until you get the barcode scanner suffix. Within your Shortcut handler build up the barcode string

The following code is adapted from something I use myself, but is untested in its current form.

    // Variables defined on Form object
GettingBarcode : boolean;
CurrentBarcode : string;
TypedInShiftState: integer; // 16=shift, 17=ctrl, 18=alt

procedure Form1.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
var
  Character:Char;
begin
  Character:=Chr(MapVirtualKey(Msg.CharCode,MAPVK_VK_TO_CHAR));
  if GettingBarcode then
  begin
    // Take care of case 
    if (TypedInShiftState<>16) and CharInSet(Character,['A'..'Z']) then
        Character:=Chr(Ord(Character)+32);
    TypedInShiftState:=0;
    // Tab and Enter programmed as suffix on barcode scanner
    if CharInSet(Character,[#9, #13]) then
    begin
      // Do something with your barcode string
      try
        HandleBarcode(CurrentBarcode);
      finally
        CurrentBarcode:='';
        Handled:=true;
        GettingBarcode:=False;
      end;
    end
    else if CharInSet(Character,[#0..#31]) then
    begin
      TypedInShiftState:=Msg.CharCode;
      Handled:=True;
    end
    else begin
      CurrentBarcode:=CurrentBarcode+Character;
      Handled:=true;
    end;
  end
  else begin
    if Character=#0 then
    begin
      TypedInShiftState:=Msg.CharCode;
    end
    else if (TypedInShiftState=18) and (Character='A') then
    begin
      GettingBarcode:=True;
      CurrentBarcode:='';
      Handled:=true;
    end;
  end;
end;
Jan Oosting
+1  A: 

Although your barcode has a USB connector. It can be programmed as a Keyboard wedge or RS232. See this page http://www.instrumentsandequipmentco.com/support/faq-metrologic.htm Where it says

Q. What is the difference between USB Keyboard and USB Point-of-Sale? When the MX009 is set-up to communicate as a USB Keyboard, the scanned data will appear in the current application that is active on your PC. The data is entered just as if the keys were pressed on the keyboard. When the MX009 is set-up to communicate as a USB Point-of-Sale device, the data is transmitted to the USB port like RS232 data and the USB port must be configured like a COM port. The MX009 leaves the factory set for either USB Keyboard or USB Point-of-Sale.

When your program accepts RS232 you no longer need focus in a text field.

  1. Reprogram your barcode as Point-of-Sale (RS232)
  2. Reprogram to send a suffix usually - carriage-return/CR/$0D at the end of the barcode.

Look for the Carriage return to know when the complete barcode is available to your code.