我使用全局键盘钩子来处理条形码阅读器。条形码阅读器在条形码之前发送一个STX字符,在条形码之后发送一个ETX字符。
ToAscii函数有时会生成正确的STX和ETX代码(0x02或0x03),但大多数情况下它会变为0x62(b)或0x63(c)。
这可以解释并最好解决吗?
为了清楚起见,我在下面添加了钩子回调:
private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
{
if (nCode >= 0)
{
// Prepare the characters and retrieve the keyboard state.
char[] characters = new char[2];
byte[] keyState = GetKeyboardState();
if (KeyPressed != null && WinAPI.ToAscii(lParam.vkCode, lParam.scanCode, keyState, characters, 0) == 1)
{
// Initialize the event arguments and fire the KeyPressed event.
GlobalKeyboardHookEventArgs e = new GlobalKeyboardHookEventArgs(characters, (int)wParam);
KeyPressed(null, e);
// Do not call the next hook if the event has been handled.
if (e.Handled)
{
return (IntPtr)1;
}
}
}
// Call the next hook.
return WinAPI.CallNextHookEx(hook, nCode, wParam, ref lParam);
}
}
答案 0 :(得分:1)
由于扫描仪是并且必须配置为USB键盘,因此我不得不使用低级键盘钩来捕获输入。但是,我现在设置扫描仪以发送键盘命令(Alt + Shift + Backspace)作为前缀和后缀,而不是使用STX / ETX字符作为前缀/后缀。
这使我可以确定条形码何时到来以及何时完成。为了防止用户意外(或有意)执行键盘命令,我实现了一个计时器。如果在100毫秒后没有收到条形码,计时器会确保取消条形码解析。
使用RegisterHotKey和UnregisterHotKey Windows API调用捕获键盘命令。
在条形码处理过程中吞咽输入时,不要吞下退格字符是非常重要的。在热键回调之前调用低级键盘钩子,吞下退格符将阻止热键回调发生。
答案 1 :(得分:0)
扫描仪充当键盘但不是。
通过调用WinApi.ToAscii
()窗口将输入转换为“有效”键映射。 ToAscii()
将0x02解释为映射到'b'的键。但这取决于当前有效的已安装/配置键盘。所以只依靠'b'和& 'c'会导致问题......俄语键盘: - )
只需使用原始输入数据,在STX / ETX之间提取数据并将该部分映射到Ascii。
该密钥代码应位于lParam.vkCode
或lParam.scanCode
中。 KBDLLHOOKSTRUCT
结果可能如下所示,但我现在无法验证
private bool _isScanningCode;
private IntPtr HookCallback(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
{
if (nCode >= 0)
{
// Prepare the characters and retrieve the keyboard state.
char[] characters = new char[2];
byte[] keyState = GetKeyboardState();
if (lParam.scanCode == 0x02)
{
_isScanningCode == true;
return (IntPtr)1; // act like key is handled
}
if (lParam.scanCode == 0x03)
{
_isScanningCode == false;
return (IntPtr)1; //act like key is handled
}
if (_isScanningCode)
{
if (KeyPressed != null &&
WinAPI.ToAscii(lParam.vkCode, lParam.scanCode, keyState, characters, 0) == 1)
{
// Initialize the event arguments and fire the KeyPressed event.
GlobalKeyboardHookEventArgs e = new GlobalKeyboardHookEventArgs(characters, (int) wParam);
KeyPressed(null, e);
// Do not call the next hook if the event has been handled.
if (e.Handled)
{
return (IntPtr) 1;
}
}
}
}
// Call the next hook.
return WinAPI.CallNextHookEx(hook, nCode, wParam, ref lParam);
}
}