Entwickler-Ecke

Windows API - Lokaler Mousehook


Nersgatt - Do 20.01.11 11:20
Titel: Lokaler Mousehook
Moin,

ich verbrenne mir gerade das erste mal die Finger an einem Mousehook. Ich möchte einen lokalen Hook haben:


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:
var Hook : Cardinal = 0;
function HookProc(nCode: Integer; MsgID: WParam; Data: LParam): LResult;

type
  TForm4 = class(TForm)
    mmo1: TMemo;
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.FormCreate(Sender: TObject);
begin
  Hook:=SetWindowsHookEx(WH_MOUSE,@HookProc,0,GetCurrentThreadID );
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin

  UnhookWindowsHookEx(Hook);
  Hook:=0;

end;

procedure TForm4.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  mmo1.Lines.Add('MouseMove');
end;

function HookProc(nCode: Integer; MsgID: WParam; Data: LParam): LResult;
begin
    if nCode < HC_ACTION then begin
       Result := CallNextHookEx(Hook, nCode, MsgID, Data);
       Exit;
    end
    else if nCode = HC_ACTION then
    begin
      Form4.mmo1.Lines.Add('MouseHook');
    end;

    Result := CallNextHookEx(Hook,nCode,MsgID,Data) ;

end;


Das funktioniert auch teilweise. Allerdings tritt nach ein paar Sekunden eine Access Violation auf. Ich hab irgendwie überhaupt keine Idee, wo die Violation ausgelöst wird, und was der Grund dafür ist.
Wäre toll wenn ihr mir helfen könntet.

Danke!
Jens


Sinspin - Do 20.01.11 16:23

Versuch es mal mit MadExcept.
Ansonsten, ich vermute das die HookProc in ein anderen Thread läuft. Du solltest also auf dein Form Synchonized zugreifen oder ne Message senden die du auswertest um den Text zu schreiben.
Zudem ist deine HookProc etwas umständlich.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
function HookProc(nCode: Integer; MsgID: WParam; Data: LParam): LResult;
begin
  if nCode = HC_ACTION then
  begin
    Form4.mmo1.Lines.Add('MouseHook'); // an der stelle sollte es immer mal knallen
  end;
  Result := CallNextHookEx(Hook, nCode, MsgID, Data) ;
end;

So sollte es eigentlich reichen, denn CallNextHookEx wird ja in jedem Fall aufgerufen.


Nersgatt - Fr 21.01.11 09:06

Danke für die Antwort. Leider komm ich so auch nicht weiter. Ich hab mir jetzt ein User-Message gemacht und schicke der Form mit SendMessage diese Message in der HookProc. Trotzdem kommt es noch zu der AccessViolation.


Sinspin - Fr 21.01.11 13:15

Hm, hast du mal MadExcept installiert und es damit mal laufen lassen? MadExcept zeigt dir recht genau an wo es geknallt hat.
Nimm statt SendMessage mal PostMessage das entkoppelt den Nachrichtenversand noch ein bisschen mehr.


Nersgatt - Fr 21.01.11 13:22

Mit PostMessage ging es auch nicht. Mit MadExept muss ich mich erst mal befassen.


Martok - Fr 21.01.11 13:39

In einem MessageHook die MessageQueue verändern ist vielleicht auch nicht so die Idee des Tages...

Die richtige Calling Convention hast du aber, oder? Ich hab das grade mal ausprobiert, hier funktionierts wunderbar (auch wenn ich mysteriöse MouseMoves bekomme, ohne dass ich was angefasst hätte).

Delphi-Quelltext
1:
function HookProc(nCode: Integer; MsgID: WParam; Data: LParam): LResult; stdcallforward;                    


Nersgatt - Fr 21.01.11 13:42

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Die richtige Calling Convention hast du aber, oder?

Ne, das war es! :zustimm:
Dankeschön!