Keyboard hook to look for F12 with delphi
Asked Answered
N

1

8

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;
Niemeyer answered 21/5, 2014 at 21:28 Comment(4)
What version of Delphi are you using? Why not use the form's KeyPreview? #6509742Fructuous
At the worst case use an ApplicationEvents. No need to hook your own application.Clad
Not sure why anyone would downvote here. The OP showed evidence of research, and example code. The OP is also new (rep=1), so the failure to clarify Delphi version is excusable.Fizzy
+1. There's no reason for a downvote here. Sufficient information and effort (including code) was provided, and the specific Delphi version is irrelevant, as the KeyPreview and OnKeyDown events have existed since Delphi 1 and still exist in the VCL TForm in XE6.Keyser
F
12

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).

Fustic answered 21/5, 2014 at 21:37 Comment(2)
Remy, yes that was it, like usual, I try to make things too complicated. I can always count on you to know the correct answer.Niemeyer
When someone gives you a correct answer, you should click the button to accept it (only works for one if there is more than one answer). That way, the answerer gets a small increase in reputation, like you did when a few of us upvoted your question, and the answer acquires a green tick, which helps other users.Cochard

© 2022 - 2024 — McMap. All rights reserved.