//鍵盤鉤子過濾函數 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);