目的:为了实现得力牌扫码枪的输入,并执行特定功能。
场景描述:此款扫码枪模拟键盘信号,并支持以回车、换行等结尾,这里采用回车结尾进行开发。
思路:使用Windows的钩子回调函数,这里模拟键盘信号所以用WH_KEYBOARD设置键盘钩子,再用键盘钩子回调函数KeyHook来进行具体的定制功能开发。
hook: HHOOK; { 定义一个钩子句柄 }
hook := SetWindowsHookEx(WH_KEYBOARD, @KeyHook, 0, GetCurrentThreadID);
键盘钩子回调主体(加上stdcall可以不定义直接使用)
[KeyboardProc——API文档]https://docs.microsoft.com/en-us/windows/win32/winmsg/keyboardproc
function KeyHook(nCode: Integer; wParam: wParam; lParam: lParam)
: LRESULT; stdcall;
begin
//尽情写代码
Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;
释放键盘钩子
UnhookWindowsHookEx(hook);
回调函数核心代码
function KeyHook(nCode: Integer; wParam: wParam; lParam: lParam)
: LRESULT; stdcall;
const
_KeyUp = $80000000; // 键盘弹起
_KeyDown = $00000000; // 键盘按下
begin
// ShowMessage('进入钩子nCode:' + IntToStr(nCode));
if nCode < 0 then
begin
Result := CallNextHookEx(hook, nCode, wParam, lParam);
exit;
end
// HC_ACTION表示钩子中有消息
else if nCode = HC_ACTION then
begin
if (lParam and _KeyUp) = _KeyUp then
begin
ShowMessage('键盘弹起');
end
// else if (lParam and _KeyDown) = _KeyDown then
// begin
// ShowMessage('键盘按下');
// end
else if (wParam >= $30) and (wParam <= $39) then // 数字
begin
yydsQrParms := yydsQrParms + IntToStr(wParam - $30);
end
else if (wParam >= $41) and (wParam <= $5A) then // 字母全部转为小写
begin
yydsQrParms := yydsQrParms + Char(wParam + 32);
end
else if (wParam = VK_OEM_5) then // VK_OEM_5表示'|'
begin
if yydsQrParms = 'yyds' then
begin
yydsQrParms := yydsQrParms + '|';
end
else
begin
ShowMessage('清空前打印:' + yydsQrParms);
yydsQrParms := '';
end;
end
else if (wParam = VK_RETURN) then // 回车键
begin
MessageBox(0, PChar('最终结果:' + yydsQrParms), '', MB_OK);
yydsQrParms := '';
end;
end;
Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;
个人总结:每一个键盘消息回调函数的nCode都为HC_ACTION(0),然后如果没有判断会有输入两次的情况,是因为key_up和key_down造成的。上述代码以[回车]判断终止进行弹窗。
输入2次,非预期效果如下图:
输入1次,完美效果如下图: