问题
I'm need hook my keyboard and found the following code (reference here) that i want use in a Delphi Console project. Happens that after the first test i noted that LowLevelKeyboardProc() function never is executed (hello never is displayed on console window). Already SetWindowsHookEx() is working fine and returning <> 0.
Then someone can help me to solve this problem please?
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
Messages,
SysUtils;
function ToUnicodeEx(wVirtKey, wScanCode: UINT; lpKeyState: PByte; pwszBuff: PWideChar; cchBuff: Integer; wFlags: UINT; dwhkl: HKL): Integer; stdcall; external 'user32.dll';
const
LLKHF_ALTDOWN = KF_ALTDOWN shr 8;
WH_KEYBOARD_LL = 13;
type
PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;
TKBDLLHOOKSTRUCT = packed record
vkCode: DWORD;
scanCode: DWORD;
flags: DWORD;
time: DWORD;
dwExtraInfo: DWORD;
end;
var
llKeyboardHook: HHOOK = 0;
AltDown, ShiftDown, CtrlDown: Boolean;
KeyBoardState: TKeyboardState;
KeyBoardLayOut: HKL;
function TranslateVirtualKey(VirtualKey: integer): WideString;
begin
Result := '';
{$Region 'Translate VirtualKey'}
case VirtualKey of
VK_RETURN: Result := sLineBreak;
VK_TAB: Result := ' ';
VK_BACK: Result := '[BackSpace]';
VK_SHIFT: Result := '[Shift]';
VK_CONTROL: Result := '[Ctrl]';
VK_MENU: Result := '[Alt]';
VK_ESCAPE: Result := '[Esc]';
VK_PAUSE: Result := '[Pause]';
VK_CAPITAL: Result := '[Caps Lock]';
VK_PRIOR: Result := '[Page Up]';
VK_NEXT: Result := '[Page Down]';
VK_END: Result := '[End]';
VK_HOME: Result := '[Home]';
VK_LEFT: Result := '[Left Arrow]';
VK_UP: Result := '[Up Arrow]';
VK_RIGHT: Result := '[Right Arrow]';
VK_DOWN: Result := '[Down Arrow]';
VK_SELECT: Result := '[Select]';
VK_PRINT: Result := '[Print Screen]';
VK_EXECUTE: Result := '[Execute]';
VK_SNAPSHOT: Result := '[Print]';
VK_INSERT: Result := '[Ins]';
VK_DELETE: Result := '[Del]';
VK_HELP: Result := '[Help]';
VK_F1: Result := '[F1]';
VK_F2: Result := '[F2]';
VK_F3: Result := '[F3]';
VK_F4: Result := '[F4]';
VK_F5: Result := '[F5]';
VK_F6: Result := '[F6]';
VK_F7: Result := '[F7]';
VK_F8: Result := '[F8]';
VK_F9: Result := '[F9]';
VK_F10: Result := '[F10]';
VK_F11: Result := '[F11]';
VK_F12: Result := '[F12]';
VK_NUMPAD0: Result := '0';
VK_NUMPAD1: Result := '1';
VK_NUMPAD2: Result := '2';
VK_NUMPAD3: Result := '3';
VK_NUMPAD4: Result := '4';
VK_NUMPAD5: Result := '5';
VK_NUMPAD6: Result := '6';
VK_NUMPAD7: Result := '7';
VK_NUMPAD8: Result := '8';
VK_NUMPAD9: Result := '9';
VK_SEPARATOR:Result := '+';
VK_SUBTRACT: Result := '-';
VK_DECIMAL: Result := '.';
VK_DIVIDE: Result := '/';
VK_NUMLOCK: Result := '[Num Lock]';
VK_SCROLL: Result := '[Scroll Lock]';
VK_PLAY: Result := '[Play]';
VK_ZOOM: Result := '[Zoom]';
VK_LWIN,
VK_RWIN: Result := '[Win Key]';
VK_APPS: Result := '[Menu]';
end;
{$EndRegion}
end;
function LowLevelKeyboardProc(nCode: Integer; wParam: wParam; lParam: lParam): HRESULT; stdcall;
var
pkbhs: PKBDLLHOOKSTRUCT;
AChr: array[0..1] of WideChar;
VirtualKey: integer;
ScanCode: integer;
ConvRes: integer;
ActiveWindow: HWND;
ActiveThreadID: DWord;
Str: widestring;
begin
pkbhs := PKBDLLHOOKSTRUCT(Pointer(lParam));
if nCode = HC_ACTION then
begin
VirtualKey := pkbhs^.vkCode;
Str := '';
if LongBool(pkbhs^.flags and LLKHF_ALTDOWN) and (not AltDown) then
begin
Str := '[Alt]';
AltDown := True;
end;
if (not LongBool(pkbhs^.flags and LLKHF_ALTDOWN)) and (AltDown) then
AltDown := False;
if (WordBool(GetAsyncKeyState(VK_CONTROL) and $8000)) and (not CtrlDown) then
begin
Str := '[Ctrl]';
CtrlDown := True;
end;
if (not WordBool(GetAsyncKeyState(VK_CONTROL) and $8000)) and (CtrlDown) then
CtrlDown := False;
if ((VirtualKey = VK_LSHIFT) or (VirtualKey = VK_RSHIFT)) and (not ShiftDown) then
begin
Str := '[Shift]';
ShiftDown := True;
end;
if (wParam = WM_KEYUP) and ((VirtualKey = VK_LSHIFT) or (VirtualKey = VK_RSHIFT)) then
ShiftDown := False;
if (wParam = WM_KEYDOWN) and ((VirtualKey <> VK_LMENU) and (VirtualKey <> VK_RMENU)) and (VirtualKey <> VK_LSHIFT) and (VirtualKey <> VK_RSHIFT) and (VirtualKey <> VK_LCONTROL) and (VirtualKey <> VK_RCONTROL) then
begin
Str := TranslateVirtualKey(VirtualKey);
if Str = '' then
begin
ActiveWindow := GetForegroundWindow;
ActiveThreadID := GetWindowThreadProcessId(ActiveWindow, nil);
GetKeyboardState(KeyBoardState);
KeyBoardLayOut := GetKeyboardLayout(ActiveThreadID);
ScanCode := MapVirtualKeyEx(VirtualKey, 0, KeyBoardLayOut);
if ScanCode <> 0 then
begin
ConvRes := ToUnicodeEx(VirtualKey, ScanCode, @KeyBoardState, @AChr, SizeOf(AChr), 0, KeyBoardLayOut);
if ConvRes > 0 then
Str := AChr;
end;
end;
end;
if Str <> '' then
writeln('hello!');
end;
Result := CallNextHookEx(llKeyboardHook, nCode, wParam, lParam);
end;
begin
try
llKeyboardHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, HInstance, 0);
Writeln(llKeyboardHook);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
回答1:
Your code is not giving the hook a chance to trigger. Your code's actual execution begins with assigning a hook:
llKeyboardHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, HInstance, 0);
Then you write out that handle to the user:
Writeln(llKeyboardHook);
Assuming no exception was raised, the very next thing is waiting for user input:
Readln;
At this point, suppose a user presses a key on the keyboard and presses enter. That causes ReadLn
to exit, thus exiting the code and terminating the application. So the hook never has a chance to actually fire.
You should be doing some sort of wait after creating the hook, such as processing Windows messages.
来源:https://stackoverflow.com/questions/57260687/lowlevelkeyboardproc-never-is-executed