Handling USB Barcode Scanner acting as a keyboard, with header/trailers from anywhere on the form
In a winforms app, I need to read input from a standard USB barcode scanner, one which makes iteself appears as a USB keyboard to windows. This has to work without giving focus to a particular control (ie, I can't say "click on this textbox then scan the barcode"). The scanner is configured to output a header and trailer to every codes it scans.
I'd rather don't go the "raw开发者_StackOverflow社区" way, ie, hooking directly into the USB input or Windows events (WM_INPUT and such).
I can of course trap the keystrokes in ProcessCmdKey, but then I don't seem to be able to properly identify the keys for the header/trailer (^~{ and }~^ respectively).
Any idea how this can be done properly in managed code?
This works, but it's kinda ugly:
[DllImportAttribute("User32.dll")]
public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpChar, int uFlags);
[DllImportAttribute("User32.dll")]
public static extern int GetKeyboardState(byte[] pbKeyState);
public static char GetAsciiCharacter(int uVirtKey, int uScanCode)
{
byte[] lpKeyState = new byte[256];
GetKeyboardState(lpKeyState);
byte[] lpChar = new byte[2];
if (ToAscii(uVirtKey, uScanCode, lpKeyState, lpChar, 0) == 1)
return (char)lpChar[0];
else
return new char();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(keyData == Keys.ShiftKey || keyData == Keys.Shift)
return base.ProcessCmdKey(ref msg, keyData);
char keyChar = GetAsciiCharacter((int) (keyData & Keys.KeyCode), (((int) msg.LParam) & 0x1000000));
if(keyChar == '\0')
return base.ProcessCmdKey(ref msg, keyData);
_currentSequence.Add(keyChar);
if (_currentSequence.ToString() == "^~{")
{
_handlingInputFromScanner = true;
_scannerBuffer.Clear();
return true;
}
if (_currentSequence.ToString() == "}~^")
{
_handlingInputFromScanner = false;
OnScannerRead.Invoke(this, new ScannerReadEventArgs { ScannerData = _scannerBuffer.ToString() });
_scannerBuffer.Clear();
return true;
}
if (keyChar == '}' || keyChar == '{' || keyChar == '~' || keyChar == '^')
{
return true;
}
if (_handlingInputFromScanner)
{
_scannerBuffer.Append(keyChar);
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
ProcessCmdKey is the right place to do it.
maybe a textbox hidden by a panel, that gets focus when the barcode is to be scanned, and then use the keydown event, that should get you the raw ascii values of the characters sent by the scanner
精彩评论