Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyboard hook to look for F12 with delphi

This question may have already been answered but I've been unable to find the proper response. I'm trying to turn toggle a debug switch when the F12 key is pressed in a form. I'm unable to use the onkeydown event since I would have to setup a separate function for each field along with the form. So I've researched and found the SetWindowsHookEx function to set a keyboard hook. This working well except I'm getting two indications the F12 key has been press each time it is pressed:

2014/05/21 14:16:43.334
Code: 0
Key: 123
KeyStroke: 5767169
KeyStroke to Hex: 00580001
2014/05/21 14:16:43.446
Code: 0
Key: 123
KeyStroke: -1067974655
KeyStroke to Hex: C0580001  Note: this should be the keystroke that reflects KEYDOWN

I see the Keystroke is a possible method to check for keydown (WM_KEYDOWN $0100). My question is how do I test Keystroke for WM_KEYDOWN?

Here is my callback function:

function KeyboardHookProc(Code: Integer; Key: Word; KeyStroke: LongInt) : LongInt;
begin
  Result := 0;
  if Code = HC_NOREMOVE then exit;
  Result := CallNextHookEx(FkbHook, Code,Key,KeyStroke);
  if Code < 0  then exit;

{
WM_KEYDOWN

}
  if (KeyStroke and WM_KEYDOWN) = 0 then { this is where I need to test but this doesn't work! }
  begin
  if Code = HC_ACTION then
  begin
    case Key of
      vk_F12: begin
          TKPMF.Memo1.Lines.Add(FormatDatetime('yyyy/mm/dd hh:nn:ss.zzz',now));
          TKPMF.Memo1.Lines.Add('Code: ' + IntToStr(Code));
          TKPMF.Memo1.Lines.Add('Key: ' + IntToStr(Key));
          TKPMF.Memo1.Lines.Add('KeyStroke: ' + IntToStr(KeyStroke));
          TKPMF.Memo1.Lines.Add('KeyStroke to Hex: ' + LongToHex(KeyStroke));
      end;
    end; {case}

  end;
  end;

end;
like image 456
Rich R Avatar asked May 21 '14 21:05

Rich R


1 Answers

You do not need to assign a different handler to each individual control's OnKeyDown event. You can assign all of them to use the same single handler. If you enable the form's KeyPreview property then you won't need to assign a handler to any of the control's at all, you can use the Form's OnKeyDown event by itself. If you need to detect the key press when you have multiple forms open, you can use the TApplication.OnMessage or TApplicationEvents.OnMessage event instead. Either way, you do not need to use a keyboard hook via SetWindowsHooKEx() at all.

The reason your hook is not working is because WM_KEYDOWN is a window message, not a Keystroke flag. Read the documentation. The Keystroke of the two messages you showed differ only in bits 30 (previous key state) and 31 (transition state).

like image 176
Remy Lebeau Avatar answered Nov 13 '22 11:11

Remy Lebeau