Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi SetWindowsHookEx冻结了我的键盘和鼠标,还有其他奇怪的事情发生了_Delphi_Winapi - Fatal编程技术网

Delphi SetWindowsHookEx冻结了我的键盘和鼠标,还有其他奇怪的事情发生了

Delphi SetWindowsHookEx冻结了我的键盘和鼠标,还有其他奇怪的事情发生了,delphi,winapi,Delphi,Winapi,我正在Delphi中编写笑话程序(发出奇怪的声音,用户使用鼠标或键盘),它使用全局钩子捕获鼠标和键盘事件。 这是负责处理此钩子的函数: procedure MKHOOK(code: Integer;wp: wParam;lp: lParam); stdcall; var hh: HHOOK; begin PlaySound('fart.wav'); CallNextHookEx(hh,code,wp,lp); end; 钩子在窗体创建时启动: procedure TForm6.Form

我正在Delphi中编写笑话程序(发出奇怪的声音,用户使用鼠标或键盘),它使用全局钩子捕获鼠标和键盘事件。
这是负责处理此钩子的函数:

procedure MKHOOK(code: Integer;wp: wParam;lp: lParam); stdcall;
var
hh: HHOOK;
begin
  PlaySound('fart.wav');
  CallNextHookEx(hh,code,wp,lp);
end;
钩子在窗体创建时启动:

procedure TForm6.FormCreate(Sender: TObject);
begin
   MH := SetWindowsHookEx(WH_MOUSE_LL,@MKHOOK,hInstance,0);
   KH := SetWindowsHookEx(WH_KEYBOARD_LL,@MKHOOK,hInstance,0);
end;
其中MH和KH是HHOOK的类型
程序结束时,钩子被删除:

procedure TForm6.FormDestroy(Sender: TObject);
begin
   UnhookWindowsHookEx(MH);
   UnhookWindowsHookEx(KH);
end;
问题开始了,当我尝试运行它时,会发生一些奇怪的事情,比如:

  • 鼠标和键盘停止工作,我必须使用ctrl+alt+del来恢复它
  • 程序执行后,当我停止时,某些键不起作用(ctrl、alt、tab)
  • 有些键会改变它们的行为,例如,当我使用箭头键时,它们会改变我的屏幕视图

这个代码有什么问题?为什么它不起作用?对不起我的英语;)

这里有几件事不对。最明显的是:

  • 在钩子中调用
    PlaySound
    代价太高。如果每次执行钩子时都调用
    PlaySound
    ,系统很容易崩溃
  • 你的钩子签名错了。它们必须是返回
    LRESULT
    的函数。在这两种情况下,文档中都对所需的返回值进行了如下描述:如果nCode小于零,则钩子过程必须返回CallNextHookEx返回的值
  • 您不进行任何错误检查。始终检查API调用是否存在错误。每个API调用的文档中都讨论了错误处理
CallNextHookEx
的第一个参数被忽略,因此您可以传递
0
。在我看来,使用单独的钩子过程更干净

钩子函数必须如下所示:

function MouseHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;

function KeyboardHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;
MH := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, hInstance, 0);
if MH = 0 then
  // handle error
KH := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, hInstance, 0);
if KH = 0 then
  // handle error
显然,这些钩子还不能起到任何作用,但在我们尝试跑步之前,让我们先走路

按如下方式安装挂钩:

function MouseHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;

function KeyboardHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;
MH := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, hInstance, 0);
if MH = 0 then
  // handle error
KH := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, hInstance, 0);
if KH = 0 then
  // handle error

我认为很明显,您没有足够详细地阅读文档。这些API很难使用。你的编码需要精确。我建议您更仔细地阅读文档

这里有几件事不对。最明显的是:

  • 在钩子中调用
    PlaySound
    代价太高。如果每次执行钩子时都调用
    PlaySound
    ,系统很容易崩溃
  • 你的钩子签名错了。它们必须是返回
    LRESULT
    的函数。在这两种情况下,文档中都对所需的返回值进行了如下描述:如果nCode小于零,则钩子过程必须返回CallNextHookEx返回的值
  • 您不进行任何错误检查。始终检查API调用是否存在错误。每个API调用的文档中都讨论了错误处理
CallNextHookEx
的第一个参数被忽略,因此您可以传递
0
。在我看来,使用单独的钩子过程更干净

钩子函数必须如下所示:

function MouseHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;

function KeyboardHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;
MH := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, hInstance, 0);
if MH = 0 then
  // handle error
KH := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, hInstance, 0);
if KH = 0 then
  // handle error
显然,这些钩子还不能起到任何作用,但在我们尝试跑步之前,让我们先走路

按如下方式安装挂钩:

function MouseHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;

function KeyboardHook(code: Integer; wp: wParam; lp: lParam): LRESULT; stdcall;
begin
  Result := CallNextHookEx(0, code, wp, lp);
end;
MH := SetWindowsHookEx(WH_MOUSE_LL, @MouseHook, hInstance, 0);
if MH = 0 then
  // handle error
KH := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, hInstance, 0);
if KH = 0 then
  // handle error

我认为很明显,您没有足够详细地阅读文档。这些API很难使用。你的编码需要精确。我建议您更仔细地阅读文档

“将未初始化的变量作为钩子参数传递”-从技术上讲,
CallNextHookEx()
忽略第一个参数,因此传递给它的内容无关紧要。您可以改为传递0,在这种情况下,两个钩子都可以使用一个钩子过程,但我不建议这样做。两个专门的程序更容易管理。@Remy看起来我对没有仔细阅读文档感到内疚!“将未初始化的变量作为钩子参数传递”-从技术上讲,
CallNextHookEx()
忽略第一个参数,因此传递给它的内容无关紧要。您可以改为传递0,在这种情况下,两个钩子都可以使用一个钩子过程,但我不建议这样做。两个专门的程序更容易管理。@Remy看起来我对没有仔细阅读文档感到内疚!