求修复:按住Ctrl时持续模拟上箭头按键的Delphi代码
修复后的Delphi低级别键盘钩子代码
原代码存在语法错误、按键判断逻辑颠倒、未过滤自注入消息导致循环、输入数组未初始化等问题,最终引发按键卡住等异常。以下是修复后的完整代码:
unit HookUnit; interface uses Windows, Messages, SysUtils, Classes; var kHook: HHOOK; implementation function LowLevelKeybdHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; var pKeyInfo: PKeybdLLHookStruct; InputArray: array[0..1] of TInput; bCtrlPressed: Boolean; begin // 仅处理符合规范的钩子消息 if nCode >= 0 then begin pKeyInfo := PKeybdLLHookStruct(lParam); // 过滤钩子自身注入的消息,避免无限循环触发 if (pKeyInfo.flags and LLKHF_INJECTED) <> 0 then begin Result := CallNextHookEx(kHook, nCode, wParam, lParam); Exit; end; // 判断Ctrl键是否处于按住状态(GetKeyState高位为1表示按下) bCtrlPressed := (GetKeyState(VK_CONTROL) < 0); case wParam of WM_KEYDOWN, WM_SYSKEYDOWN: begin // 当Ctrl按住且当前按下的不是上箭头时,模拟Ctrl+上箭头按下 if bCtrlPressed and (pKeyInfo.vkCode <> VK_UP) then begin // 清空输入数组,避免垃圾数据引发异常操作 ZeroMemory(@InputArray, SizeOf(InputArray)); // 发送Ctrl按下(确保状态同步) InputArray[0].Itype := INPUT_KEYBOARD; InputArray[0].ki.wVk := VK_CONTROL; // 发送上箭头按下 InputArray[1].Itype := INPUT_KEYBOARD; InputArray[1].ki.wVk := VK_UP; SendInput(2, InputArray[0], SizeOf(TInput)); end; end; WM_KEYUP, WM_SYSKEYUP: begin // 当Ctrl松开时,同步抬起上箭头和Ctrl键 if (pKeyInfo.vkCode = VK_CONTROL) then begin ZeroMemory(@InputArray, SizeOf(InputArray)); // 发送上箭头抬起 InputArray[0].Itype := INPUT_KEYBOARD; InputArray[0].ki.wVk := VK_UP; InputArray[0].ki.dwFlags := KEYEVENTF_KEYUP; // 发送Ctrl抬起 InputArray[1].Itype := INPUT_KEYBOARD; InputArray[1].ki.wVk := VK_CONTROL; InputArray[1].ki.dwFlags := KEYEVENTF_KEYUP; SendInput(2, InputArray[0], SizeOf(TInput)); end; end; end; end; // 传递消息给下一个钩子 Result := CallNextHookEx(kHook, nCode, wParam, lParam); end; // 安装钩子 function InstallKeyHook: Boolean; begin kHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeybdHookProc, HInstance, 0); Result := kHook <> 0; end; // 卸载钩子 procedure UninstallKeyHook; begin if kHook <> 0 then begin UnhookWindowsHookEx(kHook); kHook := 0; end; end; initialization InstallKeyHook; finalization UninstallKeyHook; end.
核心修复说明
- 语法修正:补全原代码缺失的语法结构,改用指针访问避免潜在问题
- 按键状态判断:使用
GetKeyState(VK_CONTROL) < 0正确判断Ctrl是否按住 - 自注入消息过滤:通过
LLKHF_INJECTED标志避免钩子捕获自身发送的模拟按键,防止无限循环 - 输入数组初始化:用
ZeroMemory清空数组,避免内存垃圾触发意外的鼠标/键盘事件 - 逻辑优化:仅在Ctrl按住且未触发上箭头时模拟组合键,Ctrl松开时同步抬起所有按键,彻底解决按键卡住问题
内容的提问来源于stack exchange,提问作者SuperPotato33
相关产品推荐
相关产品推荐

