这个问题可能已经得到解答,但我一直无法找到正确的答案.我正试图在表单中按下F12键时切换调试开关.我无法使用onkeydown事件,因为我必须为每个字段设置一个单独的函数以及表单.所以我研究并发现了SetWindowsHookEx函数来设置键盘钩子.这个工作得很好,除了我得到两个指示F12键每次按下时都按下:
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
我看到Keystroke是检查keydown的可能方法(WM_KEYDOWN $ 0100).我的问题是如何为WM_KEYDOWN测试击键?
这是我的回调函数:
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;
Remy Lebeau.. 12
您不需要为每个控件的OnKeyDown
事件分配不同的处理程序.您可以指定所有这些使用相同的单个处理程序.如果启用表单的KeyPreview
属性,则根本不需要为任何控件分配处理程序,您可以单独使用表单的OnKeyDown
事件.如果在打开多个表单时需要检测按键,则可以使用TApplication.OnMessage
或TApplicationEvents.OnMessage
事件.无论哪种方式,您根本不需要使用键盘钩子SetWindowsHooKEx()
.
钩子无法工作的原因是因为WM_KEYDOWN
是窗口消息,而不是按键标志.阅读文档.您显示的两条消息的击键区别仅在于位30(先前的键状态)和31(过渡状态).
您不需要为每个控件的OnKeyDown
事件分配不同的处理程序.您可以指定所有这些使用相同的单个处理程序.如果启用表单的KeyPreview
属性,则根本不需要为任何控件分配处理程序,您可以单独使用表单的OnKeyDown
事件.如果在打开多个表单时需要检测按键,则可以使用TApplication.OnMessage
或TApplicationEvents.OnMessage
事件.无论哪种方式,您根本不需要使用键盘钩子SetWindowsHooKEx()
.
钩子无法工作的原因是因为WM_KEYDOWN
是窗口消息,而不是按键标志.阅读文档.您显示的两条消息的击键区别仅在于位30(先前的键状态)和31(过渡状态).