//键盘钩子过滤函数 function 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; iCode:=-1; Result := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam); 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); // 解除 Keyboard Hook 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;
//DLL的退出处理过程 procedure KeyHookExit; far; begin if hOldKeyHook <> 0 then DisableKeyHook; UnMapViewOfFile(Shared); // 释放内存映象文件 CloseHandle(MemFile); // 关闭映象文件 ExitProc := ProcSaveExit; end;
procedure TForm1.bReadKeysClick(Sender: TObject); // 取得击键的历史记录 var i:Integer; begin Memo1.Lines.Clear; // 在Memo1中显示击键历史记录 for i:=0 to GetKeyCount-1 do Memo1.Text:=Memo1.Text+GetKey(i); end;
procedure TForm1.bClearKeysClick(Sender: TObject); // 清除击键历史记录 begin Memo1.Clear; ClearKeyString; end;
end. // 源代码结束
三、 Windows95下DLL中实现共享内存 在上面的钩子函数所在的DLL文件中,需要使用共享内存,即,所有击键的记录存储在同一个数据段中。为什么要这样做呢?这是因为Windows95的DLL调用方法与Windows3.X的方法不同。每个进(线)程在登录某动态连接库时都会为该动态连接库传入一个新的实例句柄(即DLL数据段的句柄)。这使得DLL各个实例之间互不干扰,但是这对那些所有DLL实例共享一组变量带来一些困难。为了解决这个问题,我们在这儿通过建立内存映射文件的方法来解决。即使用Windows的OpenFileMapping、CreateFileMapping和 MapViewOfFile三个函数来实现。使用方法如下: … MemFile是THandle类型,Shared是指针类型,HOOK_MEM_FILENAME是一常量串 … MemFile:=OpenFileMapping(FILE_MAP_WRITE,False, HOOK_MEM_FILENAME); //打开内存映射文件 if MemFile=0 then //打开失败则?_c2建内存映射文件 MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0, SizeOf(TShared) ,HOOK_MEM_FILENAME); //映射文件到变量 Shared:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);