但這裡又有了新問題: 鉤子函數返回鍵值時怎麼...不是一個?
先提醒: 在前面用 Beep 測試時, 你有沒有發現那個聲音也不只一次, 這是一個道理.
因為按一次鍵就會發出兩個消息: WM_KEYDOWN、WM_KEYUP, 我們沒有指定攔截哪個, 就都攔截了.
那怎麼區分這兩個消息呢? 秘密在鍵盤鉤子函數的第三個參數 lParam 裡面, 等下一個話題再研究吧.
//示例代碼:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Memo1: TMemo;
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
{鉤子函數聲明}
function MyKeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
hook: HHOOK;
function MyKeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
Form1.Memo1.Lines.Add(IntToStr(wParam)); {參數二是鍵值}
Result := 0; {分別測試返回 0 或非 0 這兩種情況}
end;
{派出鉤子}
procedure TForm1.Button1Click(Sender: TObject);
begin
hook := SetWindowsHookEx(WH_KEYBOARD, MyKeyHook, HInstance, GetCurrentThreadId);
Memo1.Clear;
Text := '鉤子啟動';
end;
{收回鉤子}
procedure TForm1.Button2Click(Sender: TObject);
begin
UnhookWindowsHookEx(hook);
Text := '鉤子關閉';
end;
{如果忘了收回鉤子...}
procedure TForm1.FormDestroy(Sender: TObject);
begin
if hook<>0 then UnhookWindowsHookEx(hook);
end;
end.
小秘密: 發現沒有, 這次在 SetWindowsHookEx 時, 第二參數(函數地址), 沒有使用 @、也沒有用 Addr, 怎麼也行呢?
因為函數名本身就是個地址.