我正在尝试挂钩鼠标和键盘事件并将它们记录到Memo1(用于鼠标)和Memo2(用于键盘)。我试图编译的代码:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, windows;
type
{ TForm1 }
TForm1 = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
function LowLevelKeybdHookProc(nCode: LongInt; WPARAM: WPARAM; lParam : LPARAM) : LRESULT; stdcall;
function LowLevelMouseHookProc(nCode: LongInt; WPARAM: WPARAM; lParam : LPARAM) : LRESULT; stdcall;
{ public declarations }
end;
KeybdLLHookStruct = record
vkCode : cardinal;
scanCode : cardinal;
flags : cardinal;
time : cardinal;
dwExtraInfo : cardinal;
end;
MouseLLHookStruct = record
pt : TPoint;
mouseData : cardinal;
flags : cardinal;
time : cardinal;
dwExtraInfo : cardinal;
end;
var
Form1: TForm1;
mHook : cardinal;
kHook : cardinal;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
UnhookWindowsHookEx(kHook);
UnhookWindowsHookEx(mHook);
end;
procedure TForm1.FormCreate(Sender: TObject);
const
wh_keybd_ll = 13;
wh_mouse_ll = 14;
begin
kHook := SetWindowsHookEx(wh_keybd_ll, @LowLevelKeybdHookProc, hInstance, 0);
mHook := SetWindowsHookEx(wh_mouse_ll, @LowLevelMouseHookProc, hInstance, 0);
end;
function TForm1.LowLevelKeybdHookProc(nCode: LongInt; WPARAM: WPARAM; lParam : LPARAM) : LRESULT; stdcall;
// possible wParam values: WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP
var
info : ^KeybdLLHookStruct absolute lParam;
lpChar : word;
kState : TKeyboardState;
begin
result := CallNextHookEx(kHook, nCode, wParam, lParam);
with info^ do
case wParam of
wm_keydown : begin
GetKeyboardState(kState);
if ToAscii(vkCode, scanCode, kState, @lpChar, 0) > 0 then Form1.Memo2.Lines.Append(format('pressed key -- %s', [char(lpChar)]));
end;
end;
end;
function TForm1.LowLevelMouseHookProc(nCode: LongInt; WPARAM: WPARAM; lParam : LPARAM) : LRESULT; stdcall;
// possible wParam values: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN, WM_RBUTTONUP
var
info : ^MouseLLHookStruct absolute lParam;
begin
result := CallNextHookEx(mHook, nCode, wParam, lParam);
with info^ do
case wParam of
wm_lbuttondown : Form1.Memo1.Lines.Append(format('pressed left button (%d, %d)' , [pt.x, pt.y]));
wm_lbuttonup : Form1.Memo1.Lines.Append(format('released left button (%d, %d)' , [pt.x, pt.y]));
wm_mbuttondown : Form1.Memo1.Lines.Append(format('pressed middle button (%d, %d)' , [pt.x, pt.y]));
wm_mbuttonup : Form1.Memo1.Lines.Append(format('released middle button (%d, %d)' , [pt.x, pt.y]));
wm_rbuttondown : Form1.Memo1.Lines.Append(format('pressed right button (%d, %d)' , [pt.x, pt.y]));
wm_rbuttonup : Form1.Memo1.Lines.Append(format('released right button (%d, %d)' , [pt.x, pt.y]));
wm_mousewheel : begin
if smallInt(mouseData shr 16) > 0
then Form1.Memo1.Lines.Append('scrolled wheel (up)')
else Form1.Memo1.Lines.Append('scrolled wheel (down)');
end;
end;
end;
end.
但它会返回这些错误:
unit1.pas(64,62) Error: Incompatible type for arg no. 2: Got "<procedure variable type of function(LongInt,LongInt,LongInt):LongInt of object;StdCall>", expected "<procedure variable type of function(LongInt,LongInt,LongInt):LongInt;StdCall>"
unit1.pas(65,62) Error: Incompatible type for arg no. 2: Got "<procedure variable type of function(LongInt,LongInt,LongInt):LongInt of object;StdCall>", expected "<procedure variable type of function(LongInt,LongInt,LongInt):LongInt;StdCall>"
我无法理解什么是“LongInt of object”以及如何解决这个问题。
答案 0 :(得分:3)
of object
表示您提供了method pointer。这是一个实例或类方法。在您的情况下,您将传递一个实例方法,其中需要一个简单的过程。
通过使用过程而不是方法来解决问题。您需要通过Self
指针以外的方式获取表单,但问题中的代码无论如何都不是Self
。顺便说一句,这本身就是一个糟糕的举动。始终使用Self
而不是与Self
具有相同值的全局变量。