Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my keyboard hook receive the same key-up and key-down events multiple times?

In my previous question, I reported that a keyboard hook was reporting everything twice when scanning a barcode.

I put that down to key down & key events and received good advice.

Having looked at it more closely I find that each digit is actually being report FOUR times!

Here's a crude "debug by print". Can anyone suggest what I might be doing wrong? Do you need more info? I could just ignore every second input, but ... yeuck! I would rather understand what is happening.

Here's what I got for a single digit 2

---------
LongParam = 196609 |  Word = 50 | 2
LongParam and $80000000 = 0
LongParam and $40000000 = 0
---------
LongParam = 196609 |  Word = 50 | 2
LongParam and $80000000 = 0
LongParam and $40000000 = 0
---------
LongParam = -1073545215 |  Word = 50 | 2
LongParam and $80000000 = 2147483648
LongParam and $40000000 = 1073741824
---------
LongParam = -1073545215 |  Word = 50 | 2
LongParam and $80000000 = 2147483648
LongParam and $40000000 = 1073741824

Update: here's my code

function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
begin
   if Code < 0 then  // http://msdn.microsoft.com/enus/library/windows/desktop/ms644984%28v=vs.85%29.aspx
   begin
      Result := CallNextHookEx(KBHook, Code, WordParam, LongParam);
      Exit;
   end;

MainForm.Memo1.Lines.Add('---------');
MainForm.Memo1.Lines.Add('LongParam = ' + IntToStr(LongParam) +  ' |  Word = ' +         IntToStr(Ord(WordParam)) + ' | ' + Char(WordParam));
MainForm.Memo1.Lines.Add('LongParam and $80000000 = ' + IntToStr(LongParam and $80000000));
MainForm.Memo1.Lines.Add('LongParam and $40000000 = ' + IntToStr(LongParam and $40000000));

   if ((LongParam and $80000000) <> $80000000)  (* not key up *)
   or ((LongParam and $40000000) <> $40000000)  (* key was not previously down *)
   then
   begin
      Result := CallNextHookEx(KBHook, Code, WordParam, LongParam);
      Exit;
   end;

   if MainForm.ScanningChemical = False then
   begin
      Result := CallNextHookEx(KBHook, Code, WordParam, LongParam);
      Exit;
   end;

At this point I have a bar code digit. But those memo lines were added before here.

like image 601
Mawg says reinstate Monica Avatar asked Mar 26 '12 02:03

Mawg says reinstate Monica


People also ask

Should I use Keyup or Keydown?

Both are used as per the need of your program and as per the convenience of the user. keyup Fires when the user releases a key, after the default action of that key has been performed. keydown Fires when the user depresses a key.

What is Keydown and Keyup?

The keydown event occurs when the key is pressed, followed immediately by the keypress event. Then the keyup event is generated when the key is released. To understand the difference between keydown and keypress, it is useful to distinguish between characters and keys.

When you trigger a key in a keyboard What value does it return?

The keyboard event object has two important properties: key and code properties that allow you to detect which key has been pressed. The key property returns the value of the key pressed while the code represents a physical key on the keyboard.


1 Answers

Your issue is related to the way how you are evaluating the value of the Code param. The documentation about the KeyboardProc callback function states :

HC_NOREMOVE The wParam and lParam parameters contain information about a keystroke message, and the keystroke message has not been removed from the message queue. (An application called the PeekMessage function, specifying the PM_NOREMOVE flag.)

To fix the problem just replace this code

   if Code < 0 then  
   begin
      Result := CallNextHookEx(KBHook, Code, WordParam, LongParam);
      Exit;
   end;

With this

   if (Code < 0) or (Code = HC_NOREMOVE ) then
   begin
      Result := CallNextHookEx(KBHook, Code, wparam, lparam);
      Exit;
   end;
like image 125
RRUZ Avatar answered Nov 15 '22 05:11

RRUZ