![]() |
Hook in Klasse einbinden...
Hi
ich habe folgendes Konstrukt(gekürzt):
Delphi-Quellcode:
nur das geht ja nicht (HIER 1), da ich so FOverAll ja nicht ansprechen kann :(
TTastaturStatistik = class(TObject)
//Tastatur private FOverAll: Int64; HookHandle: Cardinal; //Set-Methoden procedure SetKeyHits(New: Int64); //Hook procedure Hook; procedure UnHook; public constructor Create; destructor Destroy; //Propertys property KeyHits:Int64 read FOverAll write SetKeyHits; end; implementation procedure TTastaturStatistik.Hook; //Hook aktivieren begin HookHandle := SetWindowsHookEx(WH_KEYBOARD_LL, LLKeyboardHookProc, hInstance, 0); //HIER 2 if HookHandle = 0 then RaiseLastOSError; end; procedure TTastaturStatistik.UnHook; //Hook deaktivieren begin if HookHandle <> 0 then begin UnhookWindowsHookEx(HookHandle); HookHandle := 0; end; end; function LLKeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; //Wenn Taste gedrückt wird begin if nCode = HC_ACTION then //lParam ist richtiger Typ Inc(FOverAll); //HIER 1 Result := CallNextHookEx(HookHandle, nCode, wParam, lParam); end; wenn ich allerdings LLKeyboardHookProc als Private der Klasse deklariere, dann kommt bei HIER 2 der Fehler das LLKeyboardHookProc eine reguläre Procedure und kein Methodenzeiger sei... hat irgendwer eine Lösung für mich? Edit: DUDEN, hilf mir :mrgreen: der Code ist übrigens im wesentlichen von Flocke... |
Re: Hook in Klasse einbinden...
Ich weiss nicht mehr genau wie es ging, aber es gibt da einen kleinen asm trick, um eine klassenmethode beim hook zu registrieren.
und es müsste auch mit
Delphi-Quellcode:
also mit dem klassennamen(!) funktionieren.
SetWindowsHookEx(WH_KEYBOARD_LL, TTastaturStatistik.LLKeyboardHookProc, hInstance, 0); //HIER 2
noch fragen? du musst mal im forum suchen, irgendwo steht der assembler trick auch. müsste sogar in dem thread von flocke sein. |
Re: Hook in Klasse einbinden...
mit dem klassennamen das geht nicht weil der unsichtbare Self-Parameter nicht bei der HookProcedure als erster Parameter mitkommt, sondern es kommt die Action mit. Als Umweg könnte man zur Laufzeit eine Procedure im Speicher erzeugen und dort fest den Self-Paremter reinpatchen. Diese zur Laufzeit erzeugte Procedure kann dann wiederum die Klassenmethode mit den entsprechenden parametern aufrufen.
|
Re: Hook in Klasse einbinden...
Du kannst es ähnlich machen wie Delphi mit den Fensterprozeduren. Dazu solltest du dir mal den Code zu "MakeObjectInstance" in Classes.pas ansehen.
Du brauchst in Assembler einen Stub wie:
Code:
LLKeyboardHookProc muss natürlich "stdcall" deklariert sein.
pop eax // Rücksprungadresse runter
push Self // Self auf den Stack legen (32-Bit Wert / Zeiger) push eax // Rücksprungadresse wieder drauf jmp TTastaturStatistik.LLKeyboardHookProc Den Speicherblock musst du dir mit
Delphi-Quellcode:
holen und dann statt deiner Prozedur eben "Block" als Zeiger bei SetWindowsHookEx angeben.
Block := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
[Nachtrag] Beispielcode (ungetestet):
Delphi-Quellcode:
Beim Opcode für PUSH bin ich mir nicht ganz sicher, bitte überprüfen.
function ClassProcAsHook(Obj: TObject; Method: Pointer): Pointer;
type PCodeBlock = ^TCodeBlock; TCodeBlock = packed record bPopEax: byte; bPushImm32: byte; lSelf: longint; bPushEax: byte; bJmpDisp32: byte; lDisp: longint; end; var Block: PCodeBlock; begin Block := VirtualAlloc(nil, SizeOf(TCodeBlock), MEM_COMMIT, PAGE_EXECUTE_READWRITE); Block^.bPopEax := $58; Block^.bPushImm32 := $68; Block^.lSelf := longint(Obj); Block^.bPushEax := $50; Block^.bJmpDisp32 := $E9; Block^.lDisp := longint(Method) - (longint(@Block^.lDisp) + 4); Result := Block; end; |
Re: Hook in Klasse einbinden...
|
Re: Hook in Klasse einbinden...
@Nico: :thumb: natürlich wesentlich besser, da nicht eben so hingehackt 8)
|
Re: Hook in Klasse einbinden...
hmmm :gruebel:
ich glaub das is mir etwas zu schnell... also ich soll zur laufzeit eine procedure erzeugen, die dann die klassen-proc aufruft? auch wenn ihr das eigentlich nicht macht, könntet ihr mir das ausnahmsweise in meinen quelltext einbauen? *ganz lieb guck* ich werds zwar auch versuchen, aber ehrlich gesagt würde ich da keine große hoffnung hegen :( |
Re: Hook in Klasse einbinden...
Also...
Das Problem ist, dass die Win32-API-Funktion eine Callback-Funktion mit einem bestimmten Funktionstyp erwartet. Methoden haben aber einen impliziten ersten Parameter (Self). Es nutzt also nichts, die Methode an die API-Funktion weiterzugeben, da sie immer inkompatibel ist. Die Lösung besteht nun darin, eine Funktion zur Laufzeit zu erzeugen (da Self nicht statisch ist), welche aufrufkompatibel zur API-Funktion ist und nichts anderes macht, als deine gewünschte Methode in der Klasse aufzurufen. Es gibt dann also zwei Callback-Funktionen: eine Callback-Methode und eine Callback-Funktion (die wiederum nur die Methode aufruft). Am besten siehst Du dir das Beispiel im o.g. Thead an. ( ![]() |
Re: Hook in Klasse einbinden...
also müsste ich das in etwa so machen:
Delphi-Quellcode:
stimmt das alles?
type
TCallback = procedure(bla: Integer); cdecl; TMethodCallback = procedure(bla: Integer) of object; cdecl; TDings = class private FCallback: TCallback; FMethodCallback: TMethodCallback; Method(bla: Integer); cdecl; end; //erstellen FCallback := TCallback(MakeCdeclCallback(TMethod(FMethodCallback), 4)); FMethodCallback := Method; procedure TDings.Method(bla: Integer); cdecl; begin ShowMessage('MethodCallback: ' + string(Text)); end; //weg damit FreeCdeclCallback(@FCallback); //Hooken HookHandle := SetWindowsHookEx(WH_KEYBOARD_LL, FCallback, hInstance, 0); |
Re: Hook in Klasse einbinden...
Eher so (auf dein erstes Beispiel angewendet, ungetestet):
Code:
So ist LLKeyboardHookProc eine Methode deiner Klasse und du kannst Self usw. darin benutzen.
TTastaturStatistik = class(TObject)
//Tastatur private FOverAll: Int64; HookHandle: Cardinal; [b]FCallback: Pointer;[/b] //Set-Methoden procedure SetKeyHits(New: Int64); //Hook procedure Hook; procedure UnHook; [b]function LLKeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;[/b] public constructor Create; destructor Destroy; //Propertys property KeyHits:Int64 read FOverAll write SetKeyHits; end; implementation procedure TTastaturStatistik.Hook; //Hook aktivieren begin [b]FCallback := MakeStdcallCallback([color=red]LLKeyboardHookProc[/color]);[/b] HookHandle := SetWindowsHookEx(WH_KEYBOARD_LL, [b]FCallback[/b], hInstance, 0); //HIER 2 if HookHandle = 0 then RaiseLastOSError; end; procedure TTastaturStatistik.UnHook; //Hook deaktivieren begin if HookHandle <> 0 then begin UnhookWindowsHookEx(HookHandle); HookHandle := 0; end; [b] if FCallback <> nil then begin FreeCallback(FCallback); FCallback := nil; end;[/b] end; function [b]TTastaturStatistik[/b].LLKeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; //Wenn Taste gedrückt wird begin if nCode = HC_ACTION then //lParam ist richtiger Typ Inc(FOverAll); //HIER 1 Result := CallNextHookEx(HookHandle, nCode, wParam, lParam); end; Bei der roten Stelle bin ich mir nicht sicher, ob da ein Cast herum muss. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz