簡單解釋用到的Api函數:
function SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc; hmod: HINST; dwThreadId: DWORD): HHOOK; stdcall;
功能:設定鉤子。如果指定了某個確定的線程就只監視那個線程,即是線程鉤子;如果為空白,即是監視所有線程的全域鉤子。
參數:第一個參數是鉤子的類型;
第二個參數是鉤子函數的地址;
第三個參數是包含鉤子函數的模組控制代碼;
第四個參數指定監視的線程;
傳回值:
如果成功返回所設鉤子的控制代碼,失敗返回False。
function UnhookWindowsHookEx(hhk: HHOOK): BOOL; stdcall;
功能:卸載某個鉤子。
參數:要卸載的鉤子的控制代碼。
傳回值:成功為True 失敗為False。
function GetKeyState(nVirtKey: Integer): SHORT; stdcall;
功能:得到鍵盤上某個鍵的狀態。
參數:按鍵的虛擬索引值。
傳回值:一個16位元,如果按下了,那麼傳回值的最高位為1即16進位800000,沒有按下就 返回0。
更詳細的請看Delphi內建的Win32 SDK手冊。
不再多說了,說多了就偏離重點了。要是你連鉤子函數都不會用可以參考我以前寫的一篇文章《學用鉤子函數》
程式如下:
還要記得要放兩個Button控制項到Form1上並設定相應的按一下滑鼠事件。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
{按鍵訊息的結構,Delphi中也沒有,自己定義吧。這也就我為什麼說用C寫
這樣的程式更好的原因之一。還必須注意的是這個結構在Windows NT 4 sp3以上系統
中才能使用}
tagKBDLLHOOKSTRUCT = packed record
vkCode: DWORD;//虛擬索引值
scanCode: DWORD;//掃描碼值(沒有用過,我也不懂^_^)
{一些擴充標誌,這個值比較麻煩,MSDN上說得也不太明白,但是
根據這個程式,這個標誌值的第六位元(二進位)為1時ALT鍵按下為0相反。}
flags: DWORD;
time: DWORD;//訊息時間戳記
dwExtraInfo: DWORD;//和訊息相關的擴充資訊
end;
KBDLLHOOKSTRUCT = tagKBDLLHOOKSTRUCT;
PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
//這個是低級鍵盤鉤子的索引值,Delphi中沒有,必須自己定義
const WH_KEYBOARD_LL = 13;
//定義一個常量好和上面哪個結構中的flags比較而得出ALT鍵是否按下
const LLKHF_ALTDOWN = $20;
var
Form1: TForm1;
hhkLowLevelKybd: HHOOK;
implementation
{
功能:低級鍵盤鉤子的回呼函數,在裡面過濾訊息
參數:nCode 是Hook的標誌
WParam 表示訊息的類型
LParam 是一個指向我們在上面定義的哪個結構KBDLLHOOKSTRUCT的指標
傳回值:如果不是0的話windows就把這個訊息丟掉,程式就不會再收到這個訊息了。
}
function LowLevelKeyboardProc(nCode: Integer;
WParam: WPARAM;LParam: LPARAM):LRESULT; stdcall;
var
fEatKeystroke: BOOL;
p: PKBDLLHOOKSTRUCT;
begin
Result := 0;
fEatKeystroke := FALSE;
p := PKBDLLHOOKSTRUCT (lParam);
//nCode值為HC_ACTION時表示WParam和LParam參數包涵了按鍵訊息
if (nCode = HC_ACTION) then
begin
//攔截按鍵訊息並測試是否是Ctrl+Esc、Alt+Tab、和Alt+Esc功能鍵。
case wParam of
WM_KEYDOWN,
WM_SYSKEYDOWN,
WM_KEYUP,
WM_SYSKEYUP:
fEatKeystroke :=
((p.vkCode = VK_TAB) and ((p.flags and LLKHF_ALTDOWN) <> 0)) or
((p.vkCode = VK_ESCAPE) and ((p.flags and LLKHF_ALTDOWN) <> 0)) or
((p.vkCode = VK_ESCAPE) and ((GetKeyState(VK_CONTROL) and $8000) <> 0));
end;
end;
if fEatKeystroke = True then
Result := 1;
if nCode <> 0 then
Result := CallNextHookEx(0, nCode, wParam, lParam);
end;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
//設定低級鍵盤鉤子
if hhkLowLevelKybd = 0 then
begin
hhkLowLevelKybd := SetWindowsHookExW(WH_KEYBOARD_LL,
LowLevelKeyboardProc, Hinstance, 0);
if hhkLowLevelKybd <> 0 then
MessageBox(Handle, '低級鍵盤鉤子設定成功!', '提示', MB_OK)
else
MessageBox(Handle, '低級鍵盤鉤子設定失敗!', '提示', MB_OK);
end
else
MessageBox(Handle, '低級鍵盤鉤子已設定!', '提示', MB_OK);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//卸載低級鍵盤鉤子
if hhkLowLevelKybd <> 0 then
if UnhookWindowsHookEx(hhkLowLevelKybd) <> False then
begin
MessageBox(Handle, '低級鍵盤鉤子卸載成功!', '提示', MB_OK);
hhkLowLevelKybd := 0;
end
else
MessageBox(Handle, '低級鍵盤鉤子卸載失敗!', '提示', MB_OK)
else
MessageBox(Handle, '沒有發現低級鍵盤鉤子!', '提示', MB_OK);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//在Form關閉的時候檢測,如果沒有卸載鉤子就卸載之
if hhkLowLevelKybd <> 0 then
UnhookWindowsHookEx(hhkLowLevelKybd);
end;
end.
程式在Delphi6+Windows2000 sp2中編譯並測試通過。
屏蔽
Var
Temp:integer;
begin
SystemParametersInfo(Spi_screensaverrunning,1,@temp,0);
end;
恢複
Var
Temp:integer;
begin
SystemParametersInfo(spi_screensaverrunning,0,@temp,0);
end;