![]() |
lokaler Hook wird immer doppelt durchlaufen?
Hallo, weil ich seit langem mal wieder einen lokalen Hook brauche, konstruierte ich mir erstmal einen solchen in Form eines quasi simpelst möglichen getMsg-Hooks. Allerdings habe ich bei dem jetzt das kuriose Prob, dass alle Messages, die an das Panel1 gehen und auf dem ich mit der Maus jetzt gerade herumklicke, diesen Hook irgendwie doppelt durchlaufen, also dann auch in der Case-Anweisung im Code doppelt gezählt werden.
Delphi-Quellcode:
function GetMsgProc (nCode: Integer; wParam, lParam: Longint): Longint; stdcall;
type MSG = record hwnd : HWND; message : UINT; wParam : DWord; lParam : DWord; time : DWORD; pt : TPOINT; end; PMSG = ^MSG; begin { } if nCode = HC_ACTION // if not nCode < 0 then begin with form4 do if PMSG(lParam)^.hwnd = Form4.panel1.handle then case PMSG(lParam)^.message of WM_LBUTTONDOWN : begin inc(LButtonDownCounter); label1.caption := IntToStr(LButtonDownCounter) end; WM_LBUTTONUP : begin inc(LButtonUpCounter); label2.caption := IntToStr(LButtonUpCounter) end; WM_LBUTTONDBLCLK : begin inc(DoppelklickCounter); label3.caption := IntToStr(DoppelklickCounter) end; end; { of case } end; Result := CallNextHookEx(Form4.HookID, nCode, wParam, lParam); end; procedure TForm4.FormCreate(Sender: TObject); begin HookID := SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc , 0, GetCurrentThreadId()); LButtonDownCounter := 0; LButtonUpCounter := 0; DoppelklickCounter := 0; end; procedure TForm4.FormDestroy(Sender: TObject); begin if HookID <> 0 then UnHookWindowsHookEx(HookID); end; Irgendwo muss hier doch noch ein winzig kleiner Fehler stecken, nur wo? (leider habe ich gerade 2 dicke Tomaten auf den Augen). |
AW: lokaler Hook wird immer doppelt durchlaufen?
Kann auf den ersten Blick auch keinen Fehler sehen. Aber warum verwendest du überhaupt
![]() Für die gezeigten Aktionen könntest du doch einfach die entsprechenden Events des Panels (OnDblClick, OnMouseDown, OnMouseUp, etc) nutzen. Wenn du mehr Messages brauchst, wäre die saubere Lösung eine eigene Panel Klasse vom TCustomPanel abzuleiten. Alternativ könntest du auch ![]() |
AW: lokaler Hook wird immer doppelt durchlaufen?
Thx für die Anregung, aber der von mir angezeigte Code war ja nur ein einfachst mögliches Testprog, um den lokalen Hook für mich intern jetzt erstmal wieder kurz reaktiviert zu haben. Nachher möchte ich so einen Hook für ein Programm nutzen, das aus vielen Formularen besteht, und wo ich mittels des Hooks dann alle Positionsänderungen dieser einzelnen Formulare mittels wm_move o. wm_moving kontrollieren (protokollieren, speziell verändern o. ganz verhindern) kann.
Außerdem geht's mir hier auch noch ein kleines bisschen ums Prinzip. So ein Hook hatte bei mir bisher nämlich eigentlich immer ganz gut geklappt, und jetzt auf einmal nicht mehr? Warum??? |
AW: lokaler Hook wird immer doppelt durchlaufen?
Ist sicher gestellt, daß
Delphi-Quellcode:
nicht zweimal aufgerufen wird?
TForm4.FormCreate
|
AW: lokaler Hook wird immer doppelt durchlaufen?
Zitat:
Ich vermute mal, dass die VCL da intern irgendwie mit den Messages hantiert und dadurch verursacht, dass diese manchmal doppelt verschickt werden. |
AW: lokaler Hook wird immer doppelt durchlaufen?
Zitat:
Zitat:
|
AW: lokaler Hook wird immer doppelt durchlaufen?
Zitat:
Mit z.B. einem simplen
Delphi-Quellcode:
showmessage('TForm4.FormCreate')
oder einem Piepton mit Zufallsfrequenz
Delphi-Quellcode:
windows.beep(200+random(1000),100)
irgendwo in der FormCreate-Prozedur ließe (huch, Konjunktiv II) sich das einfach verifizieren oder falsifizieren. Dann könnte (huch, schon wieder Konjunktiv II) man auch auf den Konjunktiv II in den Antworten verzichten. |
AW: lokaler Hook wird immer doppelt durchlaufen?
Damit auch für die Grammatikprofis :shock: alle Zweifel restlos ausgeräumt sind: Es blieb bei nur einem Meldungsfenster bzw. auch bei nur einem Ton.
|
AW: lokaler Hook wird immer doppelt durchlaufen?
Zitat:
Das waren nur zwei Beispiele, wie man schnell - ohne Debugger - das Durchlaufen von Code feststellen kann, ich benutze derlei jedenfalls ziemlich oft. Vielleicht gibt es noch mehr und geeignetere Methoden?! |
AW: lokaler Hook wird immer doppelt durchlaufen?
Hast du schon mal einen Haltepunkt gesetzt und den Aufruf-Stack angeschaut?
|
AW: lokaler Hook wird immer doppelt durchlaufen?
Zitat:
Demgemäß scheint es also doch normal zu sein, dass zumindest eine GetMsgProc bei jeder Message zweimal aufgerufen wird. Nämlich einmal mit der Message wo diese noch nicht von der Message-Schlange heruntergenommen wurde, und ein zweites Mal wo das schon geschehen ist und wo diese Message dann anschließend (nach der Hook-Kette) direkt zur WndProc des Control weitergeschickt werden wird. Soll heißen (zumindest für mich): Wenn man auf eine Message in so einer GetMsgProc reagieren möchte, dann muss man also auch diesen wParameter noch mit berücksichtigen und kann so auch nochmal ein bisschen genauer auf die Situation reagieren ...schon bei einer angänglichen Vorab-Betrachtung der Message, bevor die überhaupt schon abgeschickt wurde, oder erst danach wenn fest steht, dass sie tatsächlich zum Control abgeschickt wurde etc. etc.. Zacherl lag also doch schon irgendwo richtig mit seiner Vermutung Zitat:
|
AW: lokaler Hook wird immer doppelt durchlaufen?
Vielleicht noch eine kleine Ergänzung dazu:
Diese pro einer Message doppelten Hook-Aufrufe gibts auch noch bei einigen anderen lokalen Hooks. Zum Beispiel auch beim lokalen Mouse-Hook (den ich bisher immer nutzte). Bei diesem war mir nur bisher noch nicht aufgefallen, weil der von mir irgendwoher kopierte Code zur Message-Bearbeitung mit <if nCode = HAction then> begann (und im MouseHook das Info, ob die Message schon von der MsgLoop gelöscht wurde, schon im 'nCode'-Parameter sitzt). Das nämlich lässt den Hook-Durchlauf mit noch nicht von der Message-Loop gelöschten Message außen vor. Den würde man bekommen mit <if nCode = HC_NOREMOVE then>. Und wenn man die Message-Bearbeitung im Mouse-Hook mit <if nCode >= 0 then> beginnt, dann bearbeitet man auch beim Mouse-Hook tatsächlich beide Hook-Durchläufe pro Message. Auch beim Keyboard-Hook (WH_KEYBOARD) dürfte das so ganz ähnlich liegen. Ob es so einen doppelten Hookdurchlauf pro Message überhaupt gibt hängt davon ab, ob beim Auslesen der Message die Api-Funktionen GetMessage oder PeekMessage beteiligt sind (dann wird der Hook vom System aufgerufen) und ob die Application zum Abgreifen dieser Message von der MsgLoop dafür z.B. 2 PeekMessage-Calls benutzt. Einen ohne die Message dabei zu löschen, und einen zweiten mit Message-Löschung und anschließend dann wohl Weiterleitung an die WndProc des jeweiligen Controls (...so +/- gemäß MSDK). Last but not least: Wer oben event. mitgelesen hat weiß, dass es mir hier letztlich um die wm_move und wm_moving -Messages ging. Messages, die man jetzt aber zufälligerweise garnicht durch einen GetMsg-Hook bekommt, sondern wofür man einen lokalen CallWnd-Hook (WH_CALLWNDPROC) benötigt. (Das nur der Vollständigkeit halber, weil's bei vielen sicher ähnlich liegt wie bei mir: Einen 'perfekten' schönen Code aus dem Internet kopiert und deswegen an dieser Sache nie vorbeigekommen :shock:) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:04 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