Entwickler-Ecke
Windows API - Mouse Hook
JohnMcClane - So 09.05.04 15:00
Titel: Mouse Hook
Hi,
Ich arbeite gerade an einem Komponentenpackage mit dem es möglich sein soll skinfähige Programme zu erstellen. Unter anderem ist auch ein HoverButton dabei, bei dem ich dann darauf gekommen bin, dass es nicht möglich ist herauszufinden, wann die maus die komp. verlässt bzw. mousemove messages zu erhalten, wenn sich die maus nicht über der eigenen Anwendung befindet. Da es in meiner Natur liegt, nicht alles immer gleich aufzugeben, habe ich ein bisschen gesucht und bin dann auf Hooks gestoßen (unter anderem Assarbad's Tut, welches ich aber nicht wirklich verstehe).
Ich habe es also mit einem Hook versucht, welchen ich in einer DLL ausgelagert habe (wie es ja sein soll), und erhalte auch Messages von dieser DLL, allerdings, und da liegt mein Problem, erhalte ich die Nachrichten weiterhin nur, wenn sich mit die Maus über der eigenen Anwendung befindet und ich kann da einfach keinen Fehler finden.
Meine dll:
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:
| library GraphicControls;
uses SysUtils, Windows, Messages, Classes;
function SetHook:Boolean; export; forward; procedure UnHook; export; forward; procedure SetWindowHandle(WindowHandle: HWND); export; forward; function HookProc(nCode: Integer; WPARAM: wParam; LPARAM: lParam):LResult; stdcall; forward;
exports SetHook index 1, UnHook index 2, SetWindowHandle index 3;
var H: HWND = 0; HookID: HHook;
function SetHook:Boolean; begin HookID := SetWindowsHookEx(WH_MOUSE, @HookProc, hInstance, 0); if HookID <> 0 then Result := True else Result := False; end;
procedure Unhook; begin UnHookWindowsHookEx(HookID); end;
procedure SetWindowHandle(WindowHandle: HWND); begin H := WindowHandle; end;
function HookProc(nCode: Integer; WPARAM: wParam; LPARAM: lParam): LResult; stdcall; begin if nCode >= 0 then begin SendMessage(H, WM_MOUSEMOVE, WPARAM, LPARAM); Result := CallNextHookEx(WH_MOUSE, nCode, wParam, lParam); end else Result := CallNextHookEx(WH_MOUSE, nCode, wParam, lParam); end; [/code]
auszug aus meiner komponente (ich möchte hier nicht den ganzen quellcode zeigen):
[code]
type THoverButton = class(TCustomControl) ... ...
implementation
function SetHook:Boolean; external 'C:\Programme\Borland\Delphi7\Lib\GraphicControls.dll'; procedure UnHook; external 'C:\Programme\Borland\Delphi7\Lib\GraphicControls.dll'; procedure SetWindowHandle(WindowHandle: HWND); external 'C:\Programme\Borland\Delphi7\Lib\GraphicControls.dll'; ...
procedure THoverButton.SetParent(AParent: TWinControl); begin inherited; if csDesigning in ComponentState then exit; .... .... if not FHooked then begin SetWindowHandle(Handle); SetHook; FHooked := True; end; end;
...
constructor THoverButton.Create(AOwner: TComponent); begin inherited Create(AOwner); ControlStyle := [csOpaque, csReplicatable, csDoubleClicks, csCaptureMouse, csClickEvents]; ... FHooked := False; end;
destructor THoverButton.Destroy; begin .... inherited Destroy; if FHooked then Unhook; end; |
Ich habe versucht SetHook im constructor aufzurufen, doch dann erhalte ich immer die Fehlermeldung: CONTROL HAS NO PARENT....
Der selbe Fehler taucht auch auf, wenn ich UnHook vor inherited Destroy aufrufe - keine Ahnung warum. Wie gesagt so funktioniert der Code zwar, aber immer noch nur wenn ich mit der Maus über meiner Anwendung bin.
Ich hoffe, dass mir dabei jemand helfen kann, denn das Problem bereitet mir schon seit längerem großen Frust und Ärger :(
Moderiert von
Motzi: Code- durch Delphi-Tags ersetzt.
JohnMcClane - So 09.05.04 17:58
Kommt schon, bitte - das is wirklich wichtig für mich. Irgendwer muss doch was wissen :cry:
bms - So 09.05.04 18:18
Ich veratte dir etwas ganz böses. Hier gib es ein geheimes Forum für alte Hasen. Da verschwören sich die alte Hasten gegen bestimmte Fragen.
Das ist auch der Grund wieso an einem Sonntag innerhalb von zwei Stunden keine Antworten auf bestimmte Fragen kommen.
:twisted: :twisted: :twisted:
JohnMcClane - So 09.05.04 19:48
Sehr witzig,
Ich hab mein Problem jetzt in den Griff bekommen, allerdings auf eine andere Art, die nicht ganz so umständlich ist, wie Hooks zu programmieren.
Für diejenigen, die es interessiert:
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:
| type THoverButton = class(TCustomControl) .... procedure MouseLeavesTheForm(var m: TMessage); .... end;
.....
procedure THoverButton.MouseLeavesTheForm(var m: TMessage); begin inherited; .... FisTracking := False; m.Result := 1; end;
....
procedure THoverButton.WMMouseMove(var Msg: TWMMouseMove); begin inherited; if not FisTracking then begin TrackMouseEvent(FevtTrack); FisTracking := True; end; end;
....
procedure THoverButton.SetParent(AParent: TWinControl); begin inherited; if csDesigning in ComponentState then exit; if AParent <> nil then begin with FevtTrack do begin cbSize := sizeOf(tagTRACKMOUSEEVENT); dwFlags := TME_LEAVE; hwndTrack := Handle; dwHoverTime := HOVER_DEFAULT; end; end; |
Funktionieren tut es, aber wobei ich mir noch ziemlich unsicher bin, ist ob ich den Track Event auch wieder aufräumen muss oder nicht ?! :?:
JohnMcClane - So 09.05.04 20:48
Zu früh gefreut, es funktioniert nicht mehr wenn man kleinere buttons hat ca. 20x20 pixel, und mit der maus sich zu schnell rausbewegt - vielleicht kann mir ja da einer helfen
Keldorn - So 09.05.04 20:59
Hallo
da gibts schon etliche beiträge dazu im Forum,
CM_MOUSELEAVE
CM_MOUSEENTER, dort solltest du fündig werden.
Mfg Frank
JohnMcClane - Mo 10.05.04 09:17
Nein da gibt es eben keine Beiträge dazu, ich habe bereits das Forum durchsucht. CM_MOUSELEAVE wird nur aufgerufen, wenn man die Maus aus der Komponente rausbewegt UND noch mit der Maus über der eigenen Anwendung oder Form ist. Hat man diese Komponente zb. am r. Rand der Form und BorderStyle der Form auf bsNone und bewegt anschliessend die Maus nach rechts, so verlässt man zwar die Komponente, ist aber NICHT mit der Maus über der eigenen Form -> d.h. es wird auch die CM_MOUSELEAVE NICHT aufgerufen.
Daher versuche ich es ja über Tracking :wink:
Ich hätte mir da eher Hilfe erhofft von Assarbad oder Luckie (der sich ja anscheinend ziemlich gut mit der WinAPI auskennt - zumindest wenn man das nach seinem Tut. beurteilt) :roll:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!