我被要求开发一个可以与现有应用程序一起工作的新应用程序。两个应用程序都将等待条形码阅读器输入。我不希望我们的操作员扫描条形码两次:一次用于现有应用程序(16 位 - 剪裁器,无源),一次用于新应用程序。为了解决这个问题,我决定使用低级键盘挂钩(用 Delphi 编写)。它看起来很完美,因为 2 个应用程序需要条形码阅读器输入,而且我的应用程序大部分时间都不会集中注意力。
当我的应用程序聚焦时,我的低级键盘钩子运行良好。例如,如果我进入 TEdit 控件,然后扫描我的条形码:
- 等待的字符将显示在 TEdit 控件中 (#02;90BDIJ#)。
- 低级挂钩将获取所有字符(#,然后是 0,然后是 2,依此类推)。
当我的应用程序不再专注时,情况会变得更糟:如果我打开记事本然后扫描我的条形码:
- 等待的字符将显示在记事本中 (#02;90BDIJ#)。
- 低级钩子会出错字符:“àé;çàbdij”
看起来键盘状态没有考虑在内!似乎不再考虑 Shift、Ctrl 甚至 Alt 键。在我的法语键盘上:
- '#' = CTRL = ALT + "
- '0' = SHIFT + à
- '2' = SHIFT + é
- ...
有谁现在如何解决这个问题?我做错了吗(我应该改用 Windows 消息吗?)。先感谢您。
FWIW 这是我的源代码:
unit Unit5;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Math;
const
LLKHF_UP = $0080;
type
tagKBDLLHOOKSTRUCT = packed record
vkCode : DWORD;
scanCode : DWORD;
flags : DWORD;
time : DWORD;
dwExtraInfo : Integer;
end;
KBDLLHOOKSTRUCT = tagKBDLLHOOKSTRUCT;
PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
var
hkHook : HHook;
function LowLevelKeyboardProc(Code, wParam, lParam: Integer): Integer; stdcall;
procedure HookIt;
procedure UnHookIt;
implementation
uses Unit1;
procedure HookIt;
begin
hkHook := SetWindowsHookEx(WH_KEYBOARD_LL,@LowLevelKeyboardProc,hInstance,0);
end;
procedure UnHookIt;
begin
UnHookWindowsHookEx(hkHook);
end;
function LowLevelKeyboardProc(Code, wParam, lParam: Integer): Integer;
var
KeyState : TKeyboardState;
NewChar: array[0..1] of Char;
Hook : PKBDLLHOOKSTRUCT;
bControlKeyDown : Boolean;
begin
Try
Hook := Pointer(lParam);
Case Code Of
HC_ACTION:
begin
If (Hook^.flags And LLKHF_UP) <> 0 Then
begin
FillChar(NewChar,2,#0);
GetKeyboardState(KeyState);
If ToAscii(Hook^.vkCode,Hook^.scanCode,KeyState,NewChar,0) = 1 Then
Form1.ListBox1.Items.Add(NewChar[0]);
end;
end;boar
end;
Finally
Result := CallNextHookEx(hkHook,Code,wParam,lParam);
end;
end;
end.