Keyboard hook to look for F12 with delphi

delphi, setwindowshookex

Solution

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

Problem

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; ```

Original source

Related problems