Autor Beitrag
noNeed 4 aNick
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Di 12.07.05 19:30 
Hi zusammen,
da ich im Moment in den meisten meiner Projekte lokale Hooks verwende und gerade Lust hatte,
wollte ich ne Klasse für meine lokalen Hooks entwickeln.

Folgendes is dabei meinem wahnsinnigen Geist entsprungen ;)
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
unit LocalHook;

interface

uses Windows, SysUtils, Classes;

type


   TLocalHook = class(TPersistent)
     private
      HookInstalled: boolean;
      HookType: Integer;

      procedure InstallHook;
      procedure UnInstallHook;

      function RealHookProc(Code: integer; wParam: word; lParam: longword): longword; stdcall;
     public
      HookID:  HHook;
      constructor Create(AType: Integer = 0);
      destructor  Destroy;

      procedure  setHookType(AType:     Integer);
      procedure  Activate;
      procedure  Deactivate;

      procedure  HookProc(Code: integer; wParam: word; lParam: longword); virtual;
      function   Active: boolean;
    end;

implementation


constructor TLocalHook.Create(AType: Integer = 0);
 begin
        inherited Create;

        HookInstalled := false;

        setHookType(AType);
 end;

destructor TLocalHook.Destroy;
 begin
        if HookInstalled then
         UnInstallHook;

        inherited Destroy;
 end;



procedure TLocalHook.setHookType(AType: Integer);
 var tmp: boolean;
 begin
        tmp := HookInstalled;

        if HookInstalled then
         UnInstallHook;

        HookType := AType;

        if tmp then
         InstallHook;
 end;

function TLocalHook.RealHookProc(Code: integer; wParam: word; lParam: longword): longword; stdcall;
 begin
        if code < HC_ACTION then
         begin
                Result := CallNextHookEx(HookID, Code, wParam, lParam);
                exit;
         end;

        HookProc(Code, wParam, lParam);

        Result := CallNextHookEx(HookID, Code, wParam, lParam);
 end;

procedure TLocalHook.HookProc(Code: integer; wParam: word; lParam: longword);
 begin

 end;

procedure TLocalHook.InstallHook;
 begin
        if HookType <= 0 then
         exit;

        if HookInstalled then
         UnInstallHook;

       HookID := SetWindowsHookEx( HookType, @RealHookProc, 0, GetCurrentThreadID() );

       HookInstalled := (HookID <> 0);
 end;

procedure TLocalHook.UnInstallHook;
 begin
        if not HookInstalled then
         exit;

        HookInstalled := not UnhookWindowsHookEx(HookID);
 end;

function TLocalHook.Active: boolean;
 begin
        Result := HookInstalled;
 end;

procedure TLocalHook.Activate;
 begin
        InstallHook;
 end;

procedure TLocalHook.Deactivate;
 begin
        UnInstallHook;
 end;

end.


Das Ganze wird bzw soll dann folgendermaßen aufgerufen werden:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
  THook = class(TLocalHook)
   public
     procedure HookProc(Code: integer; wParam: word; lParam: longword); override;
   end;

//...

procedure THook.HookProc(Code: integer; wParam: word; lParam: longword);
  type  PMsg =  ^TMsg;
  var   msg:            PMsg;
 begin
         msg := PMsg(lParam);

         if msg^.message = WM_KEYDOWN then
          begin
                ShowMessage('Hello World');
          end;
 end;

//...

        Hook := THook.Create(WH_GETMESSAGE);
        Hook.Activate;

//...


Wenn ich das Ganze jetzt aber compilen möchte kommt in dieser Zeile nen Fehler:
ausblenden Delphi-Quelltext
1:
HookID := SetWindowsHookEx( HookType, @RealHookProc, 0, GetCurrentThreadID() );					

Delphi Debugger hat folgendes geschrieben:

[Fehler] LocalHook.pas(94): Variable erforderlich


Was kann ich da jetzt tun??

ThxinAdv
Alex


Zuletzt bearbeitet von noNeed 4 aNick am Di 12.07.05 19:55, insgesamt 1-mal bearbeitet
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 12.07.05 19:41 
Durch diese Formatierung blickst du durch?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure THook.HookProc(Code: integer; wParam: word; lParam: longword);  
  type  PMsg =  ^TMsg;  
  var   msg:            PMsg;  
 begin  
         msg := PMsg(lParam);  

 
         if msg^.message = WM_KEYDOWN then  
          begin  
                ShowMessage('Hello World');  
          end;  
 end;

Ich würde fast wetten in diser chaotischen Formatierung verbirgt sichd er Fehler.

Da wird wohl irgendwo eine Variable erwartet aber du hast da ein Konstante oder so.
noNeed 4 aNick Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Di 12.07.05 19:52 
user profile iconLuckie hat folgendes geschrieben:

Durch diese Formatierung blickst du durch?
Ich würde fast wetten in diser chaotischen Formatierung verbirgt sichd er Fehler.

1.) Ja, warum auch nicht?

2.) Um wieviel? Ich wette gerne, wenn ich weiß, dass ich gewinne :P

Abgesehen von der 'Type Zeile', die eingefügt hatte und die dadurch noch ne auf einen anderen Typebereich passende
Leerzeichen-Anzahl hat, halte ich das Ganze für recht übersichtlich.
Es sei denn du hast ne Auflösung @ ca. 640x480. Dann wird's zugegebenermaßen eng..

Weiterhin glaube ich, dass an dem schönen Spruch 'Nur Kleingeister halten Ordnung, Genies überblicken das Chaos' was Wahres dran ist ;P

user profile iconLuckie hat folgendes geschrieben:

Da wird wohl irgendwo eine Variable erwartet aber du hast da ein Konstante oder so.

Glaube ich nicht.
@RealHookProc macht das Problem und SetWindowsHookExt rufe ich sonst immer auch mit nem Pointer auf ne Funktion auf.

Ich denke das Problem ist, dass RealHookProc eine Funktion einer Klasse (TLocalHook) ist. Denn wenn ich sie außerhalb der Klasse definiere, funktioniert der Code bzw es gibt nen Fehler, weil die HookID, die ich in der Funktion verwende undefiniert ist.
Problem ist also, dass ich auf die HookID, die ich in dieser Funktion ja brauche nicht mehr zugreifen kann, da die RealHookProc außerhalb ihrer Klasse nicht weiß, welcher Variable/Klasse sie angehört.

Ich hoffe ich konnte das einigermaßen verständlich erklären...
Muetze1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 346



BeitragVerfasst: Di 12.07.05 20:44 
Moin!

Grundlegend sehe ich hier das Problem, das die WinAPI Funktion eine Procedure haben will und man eine Methode übergibt. Eine Methode hat aber einen versteckten Self-Parameter was die Nutzung bei er WinAPI Funktion ausschliesst. Auch sehe ich das Problem der Überschreibbarkeit der Methode, wodurch die einfache Angabe einer Adresse der Methode in der Klasse nicht möglich sein sollte. Daher wahrscheinlich auch die Fehlermeldung.

Grundlegend muss eine Procedure der WinAPI übergeben werden. Diese sollte aber zur Methode umgemünzt werden, damit es in der Klasse klappt. Nun ist das gleiche Problem bei der WndProc() von der VCL auch gelöst worden. Grundlegend muss eine Methode an die WinAPI gegeben werden, die VCL schafft es trotzdem dies in eine Methode umzubiegen. Daher nun die Frage: Wer kann Details dazu liefern und sagen wie man es macht?

MfG
Muetze1

_________________
49 63 68 68 61 62 65 6B 65 69 6E 65 41 68 6E 75 6E 67 21
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 12.07.05 22:49 

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
noNeed 4 aNick Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 20



BeitragVerfasst: Mi 13.07.05 00:43 
Hi BenBE, MakeObjectInstance ist leider nur für WndProcs gedacht, daher kann ich ihr meine HookProc nicht übergeben...

Hab aber mit user profile iconMotzi und durch SwissDelphiCenter (...Methodenzeiger in Funktionszeiger konvertieren?) diese Lösung rausbekommen:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
unit LocalHook;

interface

uses Windows, SysUtils, Classes;

type

   THookProc = function(Code: integer; wParam: word; lParam: longword):longword of object; stdcall;

   TLocalHook = class(TPersistent)
     private
      HookInstalled: boolean;
      HookType: Integer;
      PRealHookProc: Pointer;
      HookID:  HHook;

      procedure InstallHook;
      procedure UnInstallHook;

      function  MakeProcInstance(H: THookProc): Pointer;
      procedure FreeProcInstance(ProcInstance: Pointer);

      function RealHookProc(Code: integer; wParam: word; lParam: longword): longword; stdcall;
     public
      constructor Create(AType: Integer = 0);
      destructor  Destroy;

      procedure  setHookType(AType:     Integer);
      procedure  Activate;
      procedure  Deactivate;

      procedure  HookProc(Code: integer; wParam: word; lParam: longword); virtual;
      function   Active: boolean;
    end;

implementation

constructor TLocalHook.Create(AType: Integer = 0);
 begin
        inherited Create;

        HookInstalled := false;

        setHookType(AType);
 end;

destructor TLocalHook.Destroy;
 begin
        if HookInstalled then
         UnInstallHook;

        inherited Destroy;
 end;



procedure TLocalHook.setHookType(AType: Integer);
 var tmp: boolean;
 begin
        tmp := HookInstalled;

        if HookInstalled then
         UnInstallHook;

        HookType := AType;

        if tmp then
         InstallHook;
 end;

function TLocalHook.RealHookProc(Code: integer; wParam: word; lParam: longword): longword; stdcall;
 begin
        if code < HC_ACTION then
         begin
                Result := CallNextHookEx(HookID, Code, wParam, lParam);
                exit;
         end;

        HookProc(Code, wParam, lParam);

        Result := CallNextHookEx(HookID, Code, wParam, lParam);
 end;

procedure TLocalHook.HookProc(Code: integer; wParam: word; lParam: longword);
 begin

 end;

procedure TLocalHook.InstallHook;
 begin
        if HookType <= 0 then
         exit;

        if HookInstalled then
         UnInstallHook;

        PRealHookProc := MakeProcInstance(RealHookProc);

       HookID := SetWindowsHookEx( HookType, PRealHookProc, 0, GetCurrentThreadID() );

       HookInstalled := (HookID <> 0);
 end;

procedure TLocalHook.UnInstallHook;
 begin
        if not HookInstalled then
         exit;

        HookInstalled := not UnhookWindowsHookEx(HookID);
 end;

function TLocalHook.Active: boolean;
 begin
        Result := HookInstalled;
 end;

procedure TLocalHook.Activate;
 begin
        InstallHook;
 end;

procedure TLocalHook.Deactivate;
 begin
        UnInstallHook;
        FreeProcInstance(PRealHookProc);
 end;

function TLocalHook.MakeProcInstance(H: THookProc): Pointer;
 var M: TMethod;
 begin
        M := TMethod(H);

        // allocate memory
        GetMem(Result, 15);


        asm
         // MOV ECX,
         MOV BYTE PTR [EAX], $B9
         MOV ECX, M.Data
         MOV DWORD PTR [EAX+$1], ECX
         // POP EDX
         MOV BYTE PTR [EAX+$5], $5A
         // PUSH ECX
         MOV BYTE PTR [EAX+$6], $51
         // PUSH EDX
         MOV BYTE PTR [EAX+$7], $52
         // MOV ECX,
         MOV BYTE PTR [EAX+$8], $B9
         MOV ECX, M.Code
         MOV DWORD PTR [EAX+$9], ECX
         // JMP ECX
         MOV BYTE PTR [EAX+$D], $FF
         MOV BYTE PTR [EAX+$E], $E1
        end;
 end;

procedure TlocalHook.FreeProcInstance(ProcInstance: Pointer);
 begin
        FreeMem(ProcInstance, 15);
 end;

end.


Danke nochmal an Alle

Bye
Alex