Я пытаюсь продублировать код в разделе Перехват ввода с клавиатуры с помощью Delphi. Ниже приведен код:
...
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
KBHook: HHook; {this intercepts keyboard input}
{callback's declaration}
function KeyboardHookProc(Code: Integer; WordParam: Word;
LongParam: LongInt): LongInt; stdcall;
public
{ Public declarations }
end;
...
...
procedure TForm1.FormCreate(Sender: TObject);
begin
{Set the keyboard hook so we can intercept keyboard input}
KBHook := SetWindowsHookEx( WH_KEYBOARD,
{callback >} @KeyboardHookProc,
HInstance,
GetCurrentThreadId() );
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{unhook the keyboard interception}
UnHookWindowsHookEx(KBHook) ;
end;
function TForm1.KeyboardHookProc(Code: Integer; WordParam: Word;
LongParam: LongInt): LongInt;
begin
ListBox1.Items.Add( 'Code: ' + Code.ToString);
ListBox1.Items.Add( ' -- WordParam: ' + WordParam.ToString);
ListBox1.Items.Add( ' -- LongParam: ' + LongParam.ToString);
ListBox1.Items.Add( '' );
Result := 0;
{To prevent Windows from passing the keystrokes
to the target window, the Result value must be a nonzero value.}
end;
...
Код не компилируется. Ошибка:
[Ошибка dcc32] Unit1.pas(43): E2036 Требуется переменная
Ошибка указывает на @KeyboardHookProc
, второй аргумент функции SetWindowsHookEx
.
Затем я попробовал WH_SHELL
и WH_GETMESSAGE
с их собственными процедурами обратного вызова, также безуспешно, с той же ошибкой.
Что я пропустил?
Замечательный. Спасибо вам всем.
Вы не можете использовать нестатический метод класса в качестве обратного вызова (ну, во всяком случае, не без размышлений). У него есть скрытый параметр Self
, о котором API не знает.
Чтобы удалить этот параметр Self
, вам нужно объявить метод как class ... static
, например:
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
KBHook: HHook; {this intercepts keyboard input}
{callback's declaration}
class function KeyboardHookProc(Code: Integer; WordParam: WPARAM;
LongParam: LPARAM): LRESULT; stdcall; static;
public
{ Public declarations }
end;
var
Form1: TForm1;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
{Set the keyboard hook so we can intercept keyboard input}
KBHook := SetWindowsHookEx( WH_KEYBOARD,
{callback >} @KeyboardHookProc,
HInstance,
GetCurrentThreadId() );
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{unhook the keyboard interception}
UnHookWindowsHookEx(KBHook) ;
end;
class function TForm1.KeyboardHookProc(Code: Integer; WordParam: WPARAM;
LongParam: LPARAM): LRESULT;
begin
Form1.ListBox1.Items.Add( 'Code: ' + Code.ToString);
Form1.ListBox1.Items.Add( ' -- WordParam: ' + WordParam.ToString);
Form1.ListBox1.Items.Add( ' -- LongParam: ' + LongParam.ToString);
Form1.ListBox1.Items.Add( '' );
Result := 0;
{To prevent Windows from passing the keystrokes
to the target window, the Result value must be a nonzero value.}
end;
В качестве альтернативы вы можете использовать отдельную функцию (как это делается в статье, на которую вы ссылаетесь) вместо использования метода класса, например:
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
KBHook: HHook; {this intercepts keyboard input}
public
{ Public declarations }
end;
var
Form1: TForm1;
...
{callback's declaration}
function KeyboardHookProc(Code: Integer; WordParam: WPARAM;
LongParam: LPARAM): LRESULT; stdcall;
begin
Form1.ListBox1.Items.Add( 'Code: ' + Code.ToString);
Form1.ListBox1.Items.Add( ' -- WordParam: ' + WordParam.ToString);
Form1.ListBox1.Items.Add( ' -- LongParam: ' + LongParam.ToString);
Form1.ListBox1.Items.Add( '' );
Result := 0;
{To prevent Windows from passing the keystrokes
to the target window, the Result value must be a nonzero value.}
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{Set the keyboard hook so we can intercept keyboard input}
KBHook := SetWindowsHookEx( WH_KEYBOARD,
{callback >} @KeyboardHookProc,
HInstance,
GetCurrentThreadId() );
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{unhook the keyboard interception}
UnHookWindowsHookEx(KBHook) ;
end;
Добро пожаловать в Delphi/ООП:
function KeyboardHookProc()
— функция,function TForm1.KeyboardHookProc()
— метод. Как и в связанном примере, вам нужно определить первое, а не второе.