//监控窗体在一定的时间内有没有鼠标和键盘事件。
procedure TForm1.Timer1Timer(Sender: TObject);
var
vLastInputInfo: TLastInputInfo;
begin
vLastInputInfo.cbSize := SizeOf(vLastInputInfo);
GetLastInputInfo(vLastInputInfo);
if GetTickCount - vLastInputInfo.dwTime > 5000 then
begin
timer1.Enabled:= false;
showmessage('超过5秒,用户未动鼠标!');
end;
end;
1.关于hook的例子
谢谢,我用HOOK搞定了,有一个例子可供大家参考
先是DLL
library HKTest;
{ 按下Ctro+B,启动记事本 }
uses
SysUtils,
Classes,
HKProc in 'HKProc.pas';
exports
EnableHotKeyHook,
DisableHotKeyHook;
begin
hNextHookProc:=0;
procSaveExit:= ExitProc;
ExitProc:= @HotKeyHookExit;
end.
unit HKProc;
interface
uses
Windows, Messages, Dialogs,Shellapi;
Var
hNextHookProc: HHook;
procSaveExit: Pointer;
function KeyboardHookHandler(iCode: Integer;wParam: WPARAM;
lParam: LPARAM): LResult; stdcall; export;
function EnableHotKeyHook: Bool; export;
function DisableHotKeyHook: Bool; export;
procedure HotKeyHookExit; far;
implementation
function KeyboardHookHandler(iCode: Integer;wParam: WPARAM;
lParam: LPARAM): LResult; stdcall; export;
const
_KeyPressMask = $80000000;
begin
Result:=0;
if iCode<0 then
begin
Result:= CallNextHookEx(hNextHookProc, iCode, wParam, lParam);
exit;
end;
//侦测Ctrl+B组合键
if ((lParam and _KeyPressMask)=0)and
(GetKeyState(vk_control)<0)and(wParam=Ord('B')) then
begin
Result:=1;
//ShellExecute(hInstance,'open','Notepad.exe','','',sw_Normal);
WinExec('Notepad.exe',sw_Normal);
end;
end;
function EnableHotKeyHook: Bool; export;
begin
Result:= False;
if hNextHookProc<>0 then exit;
//挂上WH_KEYBOARD 的HOOK, 同时,传回值必须保留下来,免的HOOK调用链断掉
hNextHookProc:= SetWindowsHookEx(WH_KEYBOARD,KeyboardHookHandler,HInstance,0);
Result:= hNextHookProc<>0;
end;
function DisableHotKeyHook: Bool; export;
begin
if hNextHookProc<>0 then
begin
UnHookWindowsHookEx(hNextHookProc);
hNextHookProc:=0 ;
MessageBeep(0);
MessageBeep(0);
end;
Result:= hNextHookProc =0;
end;
procedure HotKeyHookExit;
begin
//如果忘了解除HOOK,自动代理解除的动作
if hNextHookProc<>0 then DisableHotKeyHook;
ExitProc:= procSaveExit;
end;
end.
下面是测试程序
program hk;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function EnableHotKeyHook: Bool;external 'HKTest.DLL';
function DisableHotKeyHook: Bool;external 'HKTest.DLL';
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if DisableHotKeyHook then
Showmessage('HotKey Testing... DONE!!');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if EnableHotKeyHook then
Showmessage('HotKey Testing...');
end;
end.
这样按Ctrl+B就可调出写字板了
2. 例子2,回放鼠标和键盘动作
Delphi建立键盘鼠标动作纪录与回放 很多的教学软件或系统监视软件可以自动记录回放用户的输入文字或点击按钮等操作操作,这个功能的实现是使用
了Windows的Hook函数。
Windows提供API函数SetwindowsHookEx来建立一个Hook,通过这个函数可以将一个程序添加到Hook链中监视Windows
消息,函数语法为:
SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc; hmod: HINST; dwThreadId: DWORD)
其中参数idHook指定建立的监视函数类型。通过Windows MSDN帮助可以看到,SetwindowsHookEx函数提供15种不同
的消息监视类型,在这里我们将使用WH_JOURNALRECORD和WH_JOURNALPLAYBACK来监视键盘和鼠标操作。参数lpfn指定消
息函数,在相应的消息产生后,系统会调用该函数并将消息值传递给该函数供处理。函数的一般形式为:
Hookproc (code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
其中code为系统指示标记,wParam和lParam为附加参数,根据不同的消息监视类型而不同。只要在程序中建立这样
一个函数再通过SetwindowsHookEx函数将它加入到消息监视链中就可以处理消息了。
在不需要监视系统消息时需要调用提供UnHookWindowsHookEx来解除对消息的监视。
WH_JOURNALRECORD和WH_JOURNALPLAYBACK类型是两种相反的Hook类型,前者获得鼠标、键盘动作消息,后者回放鼠
标键盘消息。所以在程序中我们需要建立两个消息函数,一个用于纪录鼠标键盘操作并保存到一个数组中,另一个用于
将保存的操作返给系统回放。
下面来建立程序,在Delphi中建立一个工程,在Form1上添加3个按钮用于程序操作。另外再添加一个按钮控件和一
个Edit控件用于验证操作。
下面是Form1的全部代码
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Edit1: TEdit;
Button4: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
EventArr:array[0..1000]of EVENTMSG;
EventLog:Integer;
PlayLog:Integer;
hHook,hPlay:Integer;
recOK:Integer;
canPlay:Integer;
bDelay:Bool;
implementation
{$R *.DFM}
Function PlayProc(iCode:Integer;wParam:wParam;lParam:lParam):LRESULT;stdcall;
begin
canPlay:=1;
Result:=0;
if iCode < 0 then //必须将消息传递到消息链的下一个接受单元
Result := CallNextHookEx(hPlay,iCode,wParam,lParam)
else if iCode = HC_SYSMODALON then
canPlay:=0
else if iCode = HC_SYSMODALOFF then
canPlay:=1
else if ((canPlay =1 )and(iCode=HC_GETNEXT)) then begin
if bDelay then begin
bDelay:=False;
Result:=50;
end;
pEventMSG(lParam)^:=EventArr[PlayLog];
end
else if ((canPlay = 1)and(iCode = HC_SKIP))then begin
bDelay := True;
PlayLog:=PlayLog+1;
end;
if PlayLog>=EventLog then begin
UNHookWindowsHookEx(hPlay);
end;
end;
function HookProc(iCode:Integer;wParam:wParam;lParam:lParam):LRESULT;stdcall;
begin
recOK:=1;
Result:=0;
if iCode < 0 then
Result := CallNextHookEx(hHook,iCode,wParam,lParam)
else if iCode = HC_SYSMODALON then
recOK:=0
else if iCode = HC_SYSMODALOFF then
recOK:=1
else if ((recOK>0) and (iCode = HC_ACTION)) then begin
EventArr[EventLog]:=pEventMSG(lParam)^;
EventLog:=EventLog+1;
if EventLog>=1000 then begin
UnHookWindowsHookEx(hHook);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption:='纪录';
Button2.Caption:='停止';
Button3.Caption:='回放';
Button4.Caption:='范例';
Button2.Enabled:=False;
Button3.Enabled:=False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
EventLog:=0;
//建立键盘鼠标操作消息纪录链
hHook:=SetwindowsHookEx(WH_JOURNALRECORD,HookProc,HInstance,0);
Button2.Enabled:=True;
Button1.Enabled:=False;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
UnHookWindowsHookEx(hHook);
hHook:=0;
Button1.Enabled:=True;
Button2.Enabled:=False;
Button3.Enabled:=True;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
PlayLog:=0;
//建立键盘鼠标操作消息纪录回放链
hPlay:=SetwindowsHookEx(WH_JOURNALPLAYBACK,PlayProc,
HInstance,0);
Button3.Enabled:=False;
end;
end.
代码添加完毕后,运行程序,点击“纪录”按钮开始纪录操作,这时你可以在文本控件中输入一些文字或者点击
“范例”按钮,然后点击“停止”按钮停止纪录,再点击“回放”按钮就可以讲先前所做的操作回放。
在上面的程序中,HookProc是纪录操作的消息函数,每当有鼠标键盘消息发生时,系统都会调用该函数,消息信
息就保存在地址lParam中,我们可以讲消息保存在一个数组中。PlayProc是消息回放函数,当系统可以执行消息回放
时调用该函数,程序就将先前纪录的消息值返回到lParam指向的区域中,系统就会执行该消息,从而实现了消息回放。
3.例子3,锁定键盘某些键
var
hNextHookProc: HHook;
function keyhook(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
Result:=0;
if Code < 0 then
begin
Result:= CallNextHookEx(hNextHookProc, Code, wParam, lParam);
exit;
end;
if wParam <> vk_Space then //?????
Result := CallNextHookEx(hNextHookProc, code, wparam, lParam)
else Result := 1; //??
//if wParam = 98 then
// UnHookWindowsHookEx(hNextHookProc);
end;
procedure TfmPasswordChange.HookOn;
begin
if hNextHookProc <> 0 then
exit;
hNextHookProc := SetWindowsHookEx(WH_KEYBOARD, keyHook, HInstance, 0);
end;
procedure TfmPasswordChange.HookOff;
begin
if hNextHookProc<>0 then
begin
UnHookWindowsHookEx(hNextHookProc);
hNextHookProc:=0;
MessageBeep(0);
MessageBeep(0);
end;
end;
// another example
unit UHookKBD;
interface
uses Windows, Messages;
type
PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
KBDLLHOOKSTRUCT = packed record
vkCode : DWORD;
scanCode : DWORD;
flags : DWORD;
time : DWORD;
dwExtraInfo : DWORD;
end;
const
LLKHF_EXTENDED = $00000001;
LLKHF_INJECTED = $00000010;
LLKHF_ALTDOWN = $00000020;
LLKHF_UP = $00000080;
LLMHF_INJECTED = $00000001;
WH_Keyboard_LL = 13;
procedure StartHook; stdcall;
procedure StopHook; stdcall;
implementation
var
OldHook: HHook;
function LowLevelHookProc(nCode:Integer; awParam: WPARAM; alParam:LPARAM): LRESULT; stdcall;
var
ControlPressed, AltPressed, EscapePressed, WinPressed, TabPressed: boolean;
pkbhs: PKBDLLHOOKSTRUCT;
FilterThis: boolean;
begin
FilterThis := false;
if nCode = HC_ACTION then
begin
pkbhs := PKBDLLHOOKSTRUCT(alParam);
ControlPressed := (GetAsyncKeyState(VK_CONTROL) and $8000) <> 0;
AltPressed := ((pkbhs^.flags and LLKHF_ALTDOWN)<>0);
EscapePressed := (pkbhs^.vkCode = VK_ESCAPE);
WinPressed := (pkbhs^.vkCode in [VK_LWIN, VK_RWIN]);
TabPressed := (pkbhs^.vkCode = VK_TAB);
// Disable WINDOWS Key
if WinPressed then
FilterThis := true
else
// Disable CTRL+ESC
if ControlPressed and EscapePressed then
FilterThis := true
else
// Disable ALT+TAB
if AltPressed and TabPressed then
FilterThis := true
else
// Disable ALT+ESC
if AltPressed and EscapePressed then
FilterThis := true
else
//Disable CTRL+ALT
if ControlPressed and AltPressed then
FilterThis := true;
end;
if not FilterThis then
Result:= CallNextHookEx (OldHook, nCode, awParam, alParam)
else
Result := 1;
end;
procedure StartHook; stdcall;
begin
OldHook := SetWindowsHookEx(WH_Keyboard_LL, LowLevelHookProc, HInstance, 0);
end;
procedure StopHook; stdcall;
begin
UnHookWindowsHookEx(OldHook);
end;
end.