Low-level keyboard hook issue : Keyboard state losed when application is not focused (Delphi)

跟風遠走 提交于 2021-02-08 07:54:37

问题


I've been asked to develop a new application that will work along side the existing one. Both application will wait for a barcode reader input. I don't want our operator to scan a barcode twice: once for the existing application (16bit - clipper, no sources) and once for the new application. To solves this issue I've decided to use a low-level keyboard hook (written in Delphi). It looks perfect since 2 applications will need the barcode reader input and that my application will not be focused the most of the time.

My low-level keyboard hook is well working when my application is focused. For example, if I enter into a TEdit control and then if I scan my barcode :

  • the awaited characters will be displayed in the TEdit control (#02;90BDIJ#).
  • the low-level hook will get all characters (# , then 0, then 2 and so on).

Things are getting worse when my application is no more focused : if I open notepad and then if I scan my barcode :

  • the awaited characters will be displayed in notepad (#02;90BDIJ#).
  • the low-level hook will get wrongs characters : "àé;çàbdij"

It looks like the Keyboard state is no taken in account ! It looks like the Shift, Ctrl or even Alt keys are no more taken in account.On my french keyboard :

  • '#' = CTRL = ALT + "
  • '0' = SHIFT + à
  • '2' = SHIFT + é
  • ...

Does anyone now how to solve this problem ? Am I doing it the wrong way (should I use windows messages instead ?). Thank you in advance.

FWIW Here is my source code :

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.

回答1:


This is a local keyboard hook. You need to create a global hook for it to work everywhere. Global keyboard (and mouse) hooks need to be implemented in a separate .dll.

Update:

I have been corrected. Apparently this does not need to be implemented in a dll.




回答2:


i encountered this issue today and was resolved by adding these lines after GetKeyboardState(KeyState);

KeyState[VK_CAPITAL] := GetKeyState(VK_CAPITAL);
KeyState[VK_SHIFT] := GetKeyState(VK_SHIFT);
KeyState[VK_CONTROL] := GetKeyState(VK_CONTROL);
KeyState[VK_MENU] := GetKeyState(VK_MENU);


来源:https://stackoverflow.com/questions/1590983/low-level-keyboard-hook-issue-keyboard-state-losed-when-application-is-not-foc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!