经过一段时间的崩溃,我不得不重新开始了
KeyboardHook的功能
function KeyboardHook(Code: Integer; wParam : WPARAM; lParam : LPARAM): LongInt;
var
Buffer: TEventMsg;
Key: Cardinal;
begin
if (wParam = $0101) 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;
启动挂钩的功能
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;
我的代码中是否有错误?
答案 0 :(得分:1)
请勿使用硬编码magic numbers。在此上下文中,13为WH_KEYBOARD_LL
,$0101
为WM_KEYUP
等。请在代码中使用实际名称。它们以Windows
和Messages
单位声明。
您是否声明KeyboardHook()
使用stdcall
调用约定?您显示的代码不是这样做的。这非常重要,因此参数值在调用堆栈上正确传递。
lParam
挂钩的WH_KEYBOARD_LL
值不是PEventMsg
(指向EVENTMSG
结构的指针)。该结构用于WH_JOURNALPLAYBACK
挂钩。 WH_KEYBOARD_LL
使用KBDLLHOOKSTRUCT
结构。 Delphi没有声明该特定结构,因此您必须在代码中自行声明它。
请勿忽略回调的Code
参数或CallNextHookEx()
的返回值。它们很重要。 wParam
和lParam
值仅在Code
参数为HC_ACTION
(0)时有效。并且CallNextHookEx()
的返回值需要在挂钩链上传递。
请改为尝试:
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
是否以跨进程安全的方式使用?