一、用Delphi做一个键盘的钩子。然后把dll中的函数导出供其它的工程使用。
二、在hookunit单元的Initialization块中做了一个共享的内存映射。保存键盘按下的信息。
三、然后再做一个函数读取这个内存区的数据。
四、以上这些编译都有问题。在另一个工程中调用dll时,把dll中定义函数据声明。安装钩子的函数也能够正常执行。然后按键盘的键子,然后调用
   读取内存区数据的函数时就报错,出现访问地址错误。
望哪位帮指点一下,谢谢。

解决方案 »

  1.   

    下面这个是dll中的单元的代码  unit UnitDll;interfaceuses
      Windows ;
    const
      BUFFER_SIZE = 16*1024 ;
      HOOK_MEM_FILENAME = 'MEM_FILE';
      HOOK_MUTEX_NAME = 'MUTEX_NAME';
    type
      TShared = record
         Keys : array[0..BUFFER_SIZE] of Char ;
         KeyCount : Integer ;
      end;
      PShared = ^TShared ;
    var
      MemFile,HookMumtex : THandle;
      hOldKeyHook : HHOOK ;
      Shared : PShared ;function KeyHookProc(icode:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall ;
    function EnabledKeyHook():BOOL ;stdcall ;
    function DisabledKeyHook():BOOL ;stdcall ;
    function GetKeyCount():Integer ;stdcall ;
    function GetKey(index:Integer):Char ;stdcall;
    procedure ClearKeyString();stdcall;implementation
      {键盘钩子函数}
      function KeyHookProc(icode:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall ;
      const
        keyPressMask = $80000000 ;
      begin
        if icode<0 then
        begin
          Result := CallNextHookEx(hOldKeyHook,icode,wParam,lParam);
        end
        else
        begin
          if (lParam and keyPressMask)=0 then
          begin
            Shared^.Keys[Shared^.KeyCount] := Char(wParam and $FF) ;//保存按键
            Inc(Shared^.KeyCount);
            if Shared^.KeyCount>=BUFFER_SIZE then
            begin
              Shared^.KeyCount := 0 ;
            end;
          end;
          Result := 0 ;
        end;
      end;  function EnabledKeyHook():BOOL ;
      begin
        Shared^.KeyCount := 0 ;
        if hOldKeyHook=0 then
        begin
          hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD,@KeyHookProc,HInstance,0);
        end;
        Result := hOldKeyHook<>0 ;
      end;  function DisabledKeyHook():BOOL ;
      begin
        if hOldKeyHook<>0 then
        begin
          UnhookWindowsHookEx(hOldKeyHook);
          hOldKeyHook := 0 ;
          Shared^.KeyCount := 0 ;
        end;
        Result := hOldKeyHook=0 ;
      end;  function GetKeyCount():Integer ;
      begin
        Result := Shared^.KeyCount ;
      end;  function GetKey(index:Integer):Char ;
      begin
       Result := Shared^.Keys[index];
      end;  procedure ClearKeyString();
      begin
        Shared^.KeyCount := 0 ;
      end;
    initialization
      HookMumtex := CreateMutex(nil,True,HOOK_MUTEX_NAME);
      MemFile := OpenFileMapping(FILE_MAP_WRITE,False,HOOK_MEM_FILENAME);  if MemFile=0 then
      begin
         MemFile := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TShared),HOOK_MEM_FILENAME);
      end;
      Shared := PShared(MapViewOfFile(MemFile,FILE_MAP_WRITE,0,0,0));
      ReleaseMutex(HookMumtex);
      CloseHandle(HookMumtex);finalization
      if hOldKeyHook<>0 then
      begin
        UnmapViewOfFile(Shared);
        CloseHandle(MemFile);
      end;
    end.
    下面的是调用这个dll的源代码。unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        btn_sethook: TButton;
        btn_cancelhook: TButton;
        btn_readkey: TButton;
        btn_clearkey: TButton;
        ListBox1: TListBox;
        procedure btn_sethookClick(Sender: TObject);
        procedure btn_cancelhookClick(Sender: TObject);
        procedure btn_readkeyClick(Sender: TObject);
        procedure btn_clearkeyClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation
      function EnabledKeyHook():BOOL; external 'KeyHook.dll';
      function DisabledKeyHook():BOOL ;external 'KeyHook.dll';
      function GetKeyCount():Integer ;external 'KeyHook.dll';
      function GetKey(index:Integer):Char ;external 'KeyHook.dll';
      procedure ClearKeyString();external 'KeyHook.dll';
    {$R *.dfm}procedure TForm1.btn_sethookClick(Sender: TObject);
    begin
      if EnabledKeyHook() then
      begin
        btn_sethook.Enabled := False ;
        btn_cancelhook.Enabled := True ;
        btn_readkey.Enabled := True ;
        btn_clearkey.Enabled := True ;
        Caption := '键盘钩子已经设置';
      end;
    end;procedure TForm1.btn_cancelhookClick(Sender: TObject);
    begin
      if DisabledKeyHook() then
      begin
        btn_sethook.Enabled := True ;
        btn_cancelhook.Enabled := False ;
        btn_readkey.Enabled := False ;
        btn_clearkey.Enabled := False ;
        Caption := '键盘钩子已经取销';
      end;
    end;procedure TForm1.btn_readkeyClick(Sender: TObject);
    var
     i : Integer ;
    begin
      for i := 0 to GetKeyCount() - 1 do
      begin
        ShowMessage(GetKey(i));
        ListBox1.Items.Text := ListBox1.Items.Text+ GetKey(i) ;
      end;end;procedure TForm1.btn_clearkeyClick(Sender: TObject);
    begin
      ListBox1.Clear ;
      ClearKeyString ;
    end;end.请指指教一下。我的操作系统是xp
      

  2.   

    《DELPHI7  windows 内核编程》 里有例子。
      

  3.   

    unit UnitDll;interfaceuses Windows;const BUFFER_SIZE = 16 * 1024;
    const HOOK_MEM_FILENAME = 'MEM_FILE';
    const HOOK_MUTEX_NAME = 'MUTEX_NAME';
    type
      TShared = record
        Keys: array[0..BUFFER_SIZE] of Char;
        KeyCount: Integer;
      end;
      PShared = ^TShared;
    var
      MemFile, HookMutex: THandle;
      hOldKeyHook: HHook;
      Shared: PShared;implementationfunction KeyHookProc(iCode: Integer; wParam: WPARAM;
      lParam: LPARAM): LRESULT; stdcall; export;
    const
      KeyPressMask = $80000000;
    begin
      if iCode < 0 then
        Result := CallNextHookEx(hOldKeyHook,
          iCode,
          wParam,
          lParam)
      else begin
        if ((lParam and KeyPressMask) = 0) then
        begin
          Shared^.Keys[Shared^.KeyCount] := Char(wParam and $00FF);
          Inc(Shared^.KeyCount);
          if Shared^.KeyCount >= BUFFER_SIZE - 1 then Shared^.KeyCount := 0;
        end;
        result:=0;
      end;
    end;
    function EnableKeyHook: BOOL; export;begin
      Shared^.KeyCount := 0;
      if hOldKeyHook = 0 then
      begin
        hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD,
          KeyHookProc,
          HInstance,
          0);
      end;
      Result := (hOldKeyHook <> 0);
    end;{撤消钩子过滤函数}
    function DisableKeyHook: BOOL; export;
    begin
      if hOldKeyHook <> 0 then
      begin
        UnHookWindowsHookEx(hOldKeyHook);
        hOldKeyHook := 0;
        Shared^.KeyCount := 0;
      end;
      Result := (hOldKeyHook = 0);
    end;function GetKeyCount: Integer; export;
    begin
      Result := Shared^.KeyCount;
    end;
    function GetKey(index: Integer): Char; export;
    begin
      Result := Shared^.Keys[index];
    end;procedure ClearKeyString; export;
    begin
      Shared^.KeyCount := 0;
    end;exports
      EnableKeyHook,
      DisableKeyHook,
      GetKeyCount,
      ClearKeyString,
      GetKey;initialization
            HookMutex := CreateMutex(nil,
              True,
              HOOK_MUTEX_NAME);
            MemFile := OpenFileMapping(FILE_MAP_WRITE,
              False,
              HOOK_MEM_FILENAME);
            if MemFile = 0 then
              MemFile := CreateFileMapping($FFFFFFFF,
                nil,
                PAGE_READWRITE,
                0,
                SizeOf(TShared),
                HOOK_MEM_FILENAME);
            Shared := MapViewOfFile(MemFile,
              File_MAP_WRITE,
              0,
              0,
              0);
            ReleaseMutex(HookMutex);
            CloseHandle(HookMutex);
    finalization
            if hOldKeyHook <> 0 then DisableKeyHook;
            UnMapViewOfFile(Shared);
            CloseHandle(MemFile);
    end.