The GetKeyState function retrieves the status of the specified virtual key. The status specifies whether the key is up, down, or toggled (on, off — alternating each time the key is pressed). SHORT GetKeyState( int nVirtKey // virtual-key code ); Return Values The return value specifies the status of the given virtual key, as follows: If the high-order bit is 1, the key is down; otherwise, it is up. If the low-order bit is 1, the key is toggled. A key, such as the caps lock key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled. example:procedure TurnCapsLockOn(bOn: Boolean); // turn the CAPS LOCK on/off var keyState: short; bToggle: Boolean; begin keyState := GetKeyState(VK_CAPITAL); bToggle := BYTE(keyState) <> 0; if bOn <> bToggle then begin keybd_event(VK_CAPITAL, 20, 0, 0); keybd_event(VK_CAPITAL, 20, KEYEVENTF_KEYUP,0); end; end;
library Key;{ Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. }uses SysUtils, Classes, windows, messages, HookKey_Unit in 'HookKey_Unit.pas';{$R *.RES} exports HookOn, HookOff;begin end. //-------------------------------------------------------------------------- unit HookKey_Unit;interface uses windows,messages; const WM_HOOKKEY = WM_USER + $1000; procedure HookOn; stdcall; procedure HookOff; stdcall; implementation var HookDeTeclado : HHook; FileMapHandle : THandle; PViewInteger : ^Integer;function CallBackDelHook( Code : Integer; wParam : WPARAM; lParam : LPARAM ) : LRESULT; stdcall;begin if code=HC_ACTION then begin FileMapHandle:=OpenFileMapping(FILE_MAP_READ,False,'TestHook'); if FileMapHandle<>0 then begin PViewInteger:=MapViewOfFile(FileMapHandle,FILE_MAP_READ,0,0,0); PostMessage(PViewInteger^,WM_HOOKKEY,wParam,lParam); UnmapViewOfFile(PViewInteger); CloseHandle(FileMapHandle); end; end; Result := CallNextHookEx(HookDeTeclado, Code, wParam, lParam) end;procedure HookOn; stdcall; begin HookDeTeclado:=SetWindowsHookEx(WH_KEYBOARD, CallBackDelHook, HInstance , 0); end;procedure HookOff; stdcall; begin UnhookWindowsHookEx(HookDeTeclado); end; end. //------------------------------以上是DLL-----------------------------------
unit TestHookKey_Unit;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;const WM_HOOKKEY= WM_USER + $1000; HookDLL = 'Key.dll'; type THookProcedure=procedure; stdcall; TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } FileMapHandle : THandle; PMem : ^Integer; HandleDLL : THandle; HookOn, HookOff : THookProcedure; procedure HookKey(var message: TMessage); message WM_HOOKKEY; public { Public declarations } end; var Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject); begin Memo1.ReadOnly:=TRUE; Memo1.Clear; HandleDLL:=LoadLibrary( PChar(ExtractFilePath(Application.Exename)+ HookDll) ); if HandleDLL = 0 then raise Exception.Create('未发现键盘钩子DLL'); @HookOn :=GetProcAddress(HandleDLL, 'HookOn'); @HookOff:=GetProcAddress(HandleDLL, 'HookOff'); IF not assigned(HookOn) or not assigned(HookOff) then raise Exception.Create('在给定的 DLL中'+#13+ '未发现所需的函数'); FileMapHandle:=CreateFileMapping( $FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(Integer), 'TestHook'); if FileMapHandle=0 then raise Exception.Create( '创建内存映射文件时出错'); PMem:=MapViewOfFile(FileMapHandle,FILE_MAP_WRITE,0,0,0); PMem^:=Handle; HookOn; end; procedure TForm1.HookKey(var message: TMessage); var KeyName : array[0..100] of char; Accion : string; begin GetKeyNameText(Message.LParam,@KeyName,100); if ((Message.lParam shr 31) and 1)=1 then Accion:='Key Up' else if ((Message.lParam shr 30) and 1)=1 then Accion:='ReKeyDown' else Accion:='KeyDown'; Memo1.Lines.add( Accion+ ': '+ String(KeyName)) ; end;procedure TForm1.FormDestroy(Sender: TObject); begin if Assigned(HookOff) then HookOff; if HandleDLL<>0 then FreeLibrary(HandleDLL); if FileMapHandle<>0 then begin UnmapViewOfFile(PMem); CloseHandle(FileMapHandle); end;end;end.
int nVirtKey // virtual-key code
);
Return Values
The return value specifies the status of the given virtual key, as follows: If the high-order bit is 1, the key is down; otherwise, it is up.
If the low-order bit is 1, the key is toggled. A key, such as the caps lock key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled. example:procedure TurnCapsLockOn(bOn: Boolean); // turn the CAPS LOCK on/off
var
keyState: short;
bToggle: Boolean;
begin
keyState := GetKeyState(VK_CAPITAL); bToggle := BYTE(keyState) <> 0; if bOn <> bToggle then
begin
keybd_event(VK_CAPITAL, 20, 0, 0);
keybd_event(VK_CAPITAL, 20, KEYEVENTF_KEYUP,0);
end;
end;
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }uses
SysUtils,
Classes,
windows,
messages,
HookKey_Unit in 'HookKey_Unit.pas';{$R *.RES}
exports
HookOn,
HookOff;begin
end.
//--------------------------------------------------------------------------
unit HookKey_Unit;interface
uses windows,messages;
const
WM_HOOKKEY = WM_USER + $1000;
procedure HookOn; stdcall;
procedure HookOff; stdcall;
implementation
var
HookDeTeclado : HHook;
FileMapHandle : THandle;
PViewInteger : ^Integer;function CallBackDelHook( Code : Integer;
wParam : WPARAM;
lParam : LPARAM
) : LRESULT; stdcall;begin
if code=HC_ACTION then
begin
FileMapHandle:=OpenFileMapping(FILE_MAP_READ,False,'TestHook');
if FileMapHandle<>0 then
begin
PViewInteger:=MapViewOfFile(FileMapHandle,FILE_MAP_READ,0,0,0);
PostMessage(PViewInteger^,WM_HOOKKEY,wParam,lParam);
UnmapViewOfFile(PViewInteger);
CloseHandle(FileMapHandle);
end;
end;
Result := CallNextHookEx(HookDeTeclado, Code, wParam, lParam)
end;procedure HookOn; stdcall;
begin
HookDeTeclado:=SetWindowsHookEx(WH_KEYBOARD, CallBackDelHook, HInstance , 0);
end;procedure HookOff; stdcall;
begin
UnhookWindowsHookEx(HookDeTeclado);
end;
end.
//------------------------------以上是DLL-----------------------------------
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;const
WM_HOOKKEY= WM_USER + $1000;
HookDLL = 'Key.dll';
type
THookProcedure=procedure; stdcall;
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FileMapHandle : THandle;
PMem : ^Integer;
HandleDLL : THandle;
HookOn,
HookOff : THookProcedure;
procedure HookKey(var message: TMessage); message WM_HOOKKEY; public
{ Public declarations }
end;
var
Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.ReadOnly:=TRUE;
Memo1.Clear;
HandleDLL:=LoadLibrary( PChar(ExtractFilePath(Application.Exename)+
HookDll) );
if HandleDLL = 0 then raise Exception.Create('未发现键盘钩子DLL');
@HookOn :=GetProcAddress(HandleDLL, 'HookOn');
@HookOff:=GetProcAddress(HandleDLL, 'HookOff');
IF not assigned(HookOn) or
not assigned(HookOff) then
raise Exception.Create('在给定的 DLL中'+#13+
'未发现所需的函数'); FileMapHandle:=CreateFileMapping( $FFFFFFFF,
nil,
PAGE_READWRITE,
0,
SizeOf(Integer),
'TestHook'); if FileMapHandle=0 then
raise Exception.Create( '创建内存映射文件时出错');
PMem:=MapViewOfFile(FileMapHandle,FILE_MAP_WRITE,0,0,0);
PMem^:=Handle;
HookOn;
end;
procedure TForm1.HookKey(var message: TMessage);
var
KeyName : array[0..100] of char;
Accion : string;
begin
GetKeyNameText(Message.LParam,@KeyName,100);
if ((Message.lParam shr 31) and 1)=1
then Accion:='Key Up'
else
if ((Message.lParam shr 30) and 1)=1
then Accion:='ReKeyDown'
else Accion:='KeyDown';
Memo1.Lines.add( Accion+
': '+
String(KeyName)) ;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(HookOff) then
HookOff;
if HandleDLL<>0 then
FreeLibrary(HandleDLL);
if FileMapHandle<>0 then
begin
UnmapViewOfFile(PMem);
CloseHandle(FileMapHandle);
end;end;end.