我的 Hook 函数停止工作
My Hook functions stop working
一段时间后崩溃,我不得不重新启动钩子
KeyboardHook 的作用
function KeyboardHook(Code: Integer; wParam : WPARAM; lParam : LPARAM): LongInt;
var
Buffer: TEventMsg;
Key: Cardinal;
begin
if (wParam = 01) and
(App.Inside) then
begin
Buffer := PEventMsg(lParam)^;
Key := Buffer.message;
if App.Inside then
begin
case Key of
VK_NEXT: App.Next;
VK_CAPITAL: App.Show;
end;
end;
end;
CallNextHookEx(Hook_ID_Keyboard, Code, wParam, lParam);
Result := 0;
end;
启动Hook的函数
function StartHookKeyboard: Boolean; stdcall;
begin
Hook_ID_Keyboard := SetWindowsHookEx(13, @KeyboardHook, HInstance, 0);
If Hook_ID_Keyboard = 0 then
Result := False else
Result := True;
end;
我的代码有没有错误?
不要使用硬编码 magic numbers。在此上下文中,13 是 WH_KEYBOARD_LL
,01
是 WM_KEYUP
,等等。在您的代码中使用实际名称。它们以 Windows
和 Messages
单位声明。
您是否声明 KeyboardHook()
使用 stdcall
调用约定?您显示的代码没有这样做。这非常重要,这样参数值才能在调用堆栈上正确传递。
WH_KEYBOARD_LL
钩子的 lParam
值不是 PEventMsg
(而是指向 EVENTMSG
structure). That structure is used for WH_JOURNALPLAYBACK
hooks. WH_KEYBOARD_LL
uses the KBDLLHOOKSTRUCT
结构的指针。Delphi 没有声明特定的结构,因此您必须自己在代码中声明它。
并且不要忽略回调的 Code
参数,或 CallNextHookEx()
的 return 值。他们很重要。 wParam
和 lParam
值仅在 Code
参数为 HC_ACTION
(0) 时有效。而CallNextHookEx()
的return值需要向上传递hook链
试试这个:
type
PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
KBDLLHOOKSTRUCT = record
vkCode: DWORD;
scanCode: DWORD;
flags: DWORD;
time: DWORD;
dwExtraInfo: ULONG_PTR;
end;
function KeyboardHook(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if Code = HC_ACTION then
begin
if (wParam = WM_KEYUP) and (App.Inside) then
begin
case PKBDLLHOOKSTRUCT(lParam)^.vkCode of
VK_NEXT: App.Next;
VK_CAPITAL: App.Show;
end;
end;
end;
// note that CallNextHookEx() ignores the first parameter,
// so you could pass 0 instead of ID_Keyboard...
Result := CallNextHookEx(Hook_ID_Keyboard, Code, wParam, lParam);
end;
function StartHookKeyboard: Boolean; stdcall;
begin
if Hook_ID_Keyboard = 0 then
Hook_ID_Keyboard := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0);
Result := Hook_ID_Keyboard <> 0;
end;
function StopHookKeyboard: Boolean; stdcall;
begin
if Hook_ID_Keyboard <> 0 then
begin
if UnhookWindowsHookEx(Hook_ID_Keyboard) then
Hook_ID_Keyboard := 0;
end;
Result := Hook_ID_Keyboard = 0;
end;
如果代码仍然崩溃,可能与 App
有关。什么是 App
?它在哪里以及如何声明?它是如何初始化的? Next()
和 Show()
实际上是做什么的?您正在全局安装挂钩以挂钩所有 运行 进程,所以 App
是否以跨进程安全的方式使用?
一段时间后崩溃,我不得不重新启动钩子
KeyboardHook 的作用
function KeyboardHook(Code: Integer; wParam : WPARAM; lParam : LPARAM): LongInt;
var
Buffer: TEventMsg;
Key: Cardinal;
begin
if (wParam = 01) and
(App.Inside) then
begin
Buffer := PEventMsg(lParam)^;
Key := Buffer.message;
if App.Inside then
begin
case Key of
VK_NEXT: App.Next;
VK_CAPITAL: App.Show;
end;
end;
end;
CallNextHookEx(Hook_ID_Keyboard, Code, wParam, lParam);
Result := 0;
end;
启动Hook的函数
function StartHookKeyboard: Boolean; stdcall;
begin
Hook_ID_Keyboard := SetWindowsHookEx(13, @KeyboardHook, HInstance, 0);
If Hook_ID_Keyboard = 0 then
Result := False else
Result := True;
end;
我的代码有没有错误?
不要使用硬编码 magic numbers。在此上下文中,13 是 WH_KEYBOARD_LL
,01
是 WM_KEYUP
,等等。在您的代码中使用实际名称。它们以 Windows
和 Messages
单位声明。
您是否声明 KeyboardHook()
使用 stdcall
调用约定?您显示的代码没有这样做。这非常重要,这样参数值才能在调用堆栈上正确传递。
WH_KEYBOARD_LL
钩子的 lParam
值不是 PEventMsg
(而是指向 EVENTMSG
structure). That structure is used for WH_JOURNALPLAYBACK
hooks. WH_KEYBOARD_LL
uses the KBDLLHOOKSTRUCT
结构的指针。Delphi 没有声明特定的结构,因此您必须自己在代码中声明它。
并且不要忽略回调的 Code
参数,或 CallNextHookEx()
的 return 值。他们很重要。 wParam
和 lParam
值仅在 Code
参数为 HC_ACTION
(0) 时有效。而CallNextHookEx()
的return值需要向上传递hook链
试试这个:
type
PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
KBDLLHOOKSTRUCT = record
vkCode: DWORD;
scanCode: DWORD;
flags: DWORD;
time: DWORD;
dwExtraInfo: ULONG_PTR;
end;
function KeyboardHook(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if Code = HC_ACTION then
begin
if (wParam = WM_KEYUP) and (App.Inside) then
begin
case PKBDLLHOOKSTRUCT(lParam)^.vkCode of
VK_NEXT: App.Next;
VK_CAPITAL: App.Show;
end;
end;
end;
// note that CallNextHookEx() ignores the first parameter,
// so you could pass 0 instead of ID_Keyboard...
Result := CallNextHookEx(Hook_ID_Keyboard, Code, wParam, lParam);
end;
function StartHookKeyboard: Boolean; stdcall;
begin
if Hook_ID_Keyboard = 0 then
Hook_ID_Keyboard := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0);
Result := Hook_ID_Keyboard <> 0;
end;
function StopHookKeyboard: Boolean; stdcall;
begin
if Hook_ID_Keyboard <> 0 then
begin
if UnhookWindowsHookEx(Hook_ID_Keyboard) then
Hook_ID_Keyboard := 0;
end;
Result := Hook_ID_Keyboard = 0;
end;
如果代码仍然崩溃,可能与 App
有关。什么是 App
?它在哪里以及如何声明?它是如何初始化的? Next()
和 Show()
实际上是做什么的?您正在全局安装挂钩以挂钩所有 运行 进程,所以 App
是否以跨进程安全的方式使用?