这是一个简单的键盘钩子程序,为什么在Form1失去焦点后,钩子就不起作用了?
还有如何把钩子响应函数中按键值传递给Form1?unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private  public
    { Public declarations }
  end;function MyKeyBordHook(iCode : Integer; WParam : WPARAM; lParam : LPARAM): LRESULT; stdcall;var
  Form1: TForm1;                                                   
  HHook: Integer;
  Ch: Integer;implementation{$R *.dfm}function MyKeyBordHook(iCode : Integer; WParam : WPARAM; lParam : LPARAM): LRESULT; stdcall;
begin
    Result:=CallNextHookEx(HHook,iCode,wParam,lParam);
    Ch:=WParam;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
    HHook:=SetWindowsHookEx(WH_KEYBOARD,MyKeyBordHook,Hinstance,0);
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    UnhookWindowsHookEx(HHook);
end;procedure TForm1.Button1Click(Sender: TObject);
begin                          //显示按键值
    Memo1.Text:=IntToStr(Ch);
end;end.

解决方案 »

  1.   

    要用全局钩子,把钩子放到dll中
      

  2.   

    啊,钩子早忘光了,今天晚上回家看钩子,我发现钩子问题一般分都比较多,HOHO!
      

  3.   

    即使写到DLL中,你的程序还是有问题的。你的ch一定是在DLL中的了,是钩子获取到的一个值,但是这个ch不是那么容易被访问到的,这也全局钩子函数的特点了,运行时,全局钩子函数会被映射到目标进程的空间中,即这个ch在每个目标进程中都会有一个副本,语句 Ch:=WParam; 只是修改了当前被钩进程中的ch,不同于你程序中的ch的。
    所以直接访问变量取得钩子结果的方式是不可行的。
    我是这样做的。用PostMessage把钩子结果发送给主程序。PostMessage的第一个参数是主程序窗体的Handle, 这个Handle不可以用静态变量传送,原因同前,全局钩子函数用静态变量传递信息是有困难的。所以这里的Handle我是搜寻主窗体得来的。unit HookU;interfaceuses Windows, Messages, SEShare;const
      WM_CAPKEY = WM_USER + $301;
      WM_CAPMOUSE = WM_USER + $302;
      WM_CAPMOUSE1 = WM_USER + $303;
      WM_CAPMOUSE2 = WM_USER + $304;
      WM_CAP2CONTROL = WM_USER + $306;function HookAllHookEx(): Boolean; export;
    procedure UnHookAllHookEx(); export;
    function HookKBHookEx(): Boolean; export;
    procedure UnHookKBHookEx(); export;implementationvar
      kbhook: HHOOK = 0;
      mshook: HHOOK = 0;  HookKeyFormHandle: HWND = 0;
      CtrlCapStatus: Byte = 0;var
      WindowList: TList;function GetWindows(
        handle: HWND; // handle to parent window
        info: LPARAM  // application-defined value
       ): Boolean; stdcall;
    begin   {}
      Result := True;
      WindowList.Add(Pointer(handle));
    end;function FindPrevInstance(clssname: string; selfhandle: HWnd): HWnd;
    var
      i: integer;
      Dest: array [0..80] of char;
    begin
      Result := 0;
      WindowList := TList.Create();
      EnumWindows(@GetWindows, 0);
      for i := 0 to WindowList.Count - 1 do
      if HWnd(WindowList[i]) <> selfhandle then
      begin
        GetClassName(Hwnd(WindowList[i]), Dest, Sizeof(Dest) - 1);
        if strlen(Dest) > 0 then
          if (String(Dest) = clssname) then
          begin
            Result := Hwnd(WindowList[i]);
            Break;
          end;
      end;
      WindowList.Free();
    end;function kbhookproc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
    begin
      Result := CallNextHookEx(kbhook, code, wparam, lparam);
      if code = HC_ACTION then
      begin
        if HookKeyFormHandle = 0 then
          HookKeyFormHandle := FindPrevInstance('TBarSvrForm', 0);    if HookKeyFormHandle <> 0 then
        if (wparam <> VK_LWIN) and (wparam <> VK_RWIN) then
        begin
          if wparam = VK_CONTROL then
          begin
            if lparam and $80000000 <> 0 then  //up
            begin
              if CtrlCapStatus = 1 then
                CtrlCapStatus := 2;
            end
            else  // down
            begin
              if CtrlCapStatus = 2 then
              begin
                CtrlCapStatus := 3;
                PostMessage(HookKeyFormHandle, WM_CAP2CONTROL, 0, 0);
              end
              else
                CtrlCapStatus := 1;
            end;
          end
          else
            CtrlCapStatus := 0;
          if CtrlCapStatus >= 3 then
            CtrlCapStatus := 0
          else
            PostMessage(HookKeyFormHandle, WM_CAPKEY, wparam, lparam);
        end;
      end;
    end;function mshookproc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
    var
      pmsrec: PMOUSEHOOKSTRUCT;
    begin
      Result := CallNextHookEx(mshook, code, wparam, lparam);
      if code = HC_ACTION then
      begin
        if HookKeyFormHandle = 0 then
          HookKeyFormHandle := FindPrevInstance('TBarSvrForm', 0);
        if HookKeyFormHandle <> 0 then
        if wparam <> WM_MOUSEMOVE then
        begin
          pmsrec := Pointer(lparam);
          PostMessage(HookKeyFormHandle, WM_CAPMOUSE1, pmsrec.pt.x, pmsrec.pt.y);
          PostMessage(HookKeyFormHandle, WM_CAPMOUSE2, pmsrec.wHitTestCode, pmsrec.dwExtraInfo);
          PostMessage(HookKeyFormHandle, WM_CAPMOUSE, wparam, pmsrec.hwnd);
        end;
      end;
    end;procedure UnHookAllHookEx();
    begin
      if kbhook <> 0 then
      begin
        UnHookWindowsHookEx(kbhook);
        kbhook := 0;
      end;
      if mshook <> 0 then
      begin
        UnHookWindowsHookEx(mshook);
        mshook := 0;
      end;
    end;
    function HookAllHookEx(): Boolean;
    begin
      kbhook := SetWindowsHookEx(WH_KEYBOARD, kbhookproc, HInstance, 0);
      mshook := SetWindowsHookEx(WH_MOUSE, mshookproc, HInstance, 0);
      if (kbhook <> 0) and (mshook <> 0) then
        Result := True
      else
      begin
        UnHookAllHookEx();
        Result := False;
      end;
    end;
    procedure UnHookKBHookEx();
    begin
      if kbhook <> 0 then
      begin
        UnHookWindowsHookEx(kbhook);
        kbhook := 0;
      end;
    end;
    function HookKBHookEx(): Boolean;
    begin
      kbhook := SetWindowsHookEx(WH_KEYBOARD, kbhookproc, HInstance, 0);
      if (kbhook <> 0) then
        Result := True
      else
      begin
        UnHookKBHookEx();
        Result := False;
      end;
    end;end.