Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Message wird nicht gesendet bei globalem Hook (https://www.delphipraxis.net/74948-message-wird-nicht-gesendet-bei-globalem-hook.html)

idontwantaname 11. Aug 2006 14:37


Message wird nicht gesendet bei globalem Hook
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo !!

Ich habe mich heute mit Hooks beschäftigt und bin auf diesesHook Tutorial gestoßen. Und das ganze funktioniert schon ganz gut. Bei globalen Hooks empfiehlt der Autor, per MMF Daten an die eigene Anwendung zu schicken. Mir war das zu kompliziert, deshalb habe ich überlegt, ich schicke meinem Fenster einfach eine Message (WM_USER + x) und passe den wParam und lParam nach meinen Wünschen an. Das funktioniert auch, aber nur so lange meine eigene Form im Vordergrund ist.
Das ist natürlich sehr seltsam. Zum schicken der Nachricht verwende ich SendMessage. Der Fehler liegt auch bei dieser Funktion, denn die Hook-Prozedur wird auch ausgeführt, wenn mein Fenster im Hintergrund ist.

Hier mal ein bisschen Code, vielleicht hilft er euch ja weiter.
Delphi-Quellcode:
// aus der DLL

const
  WM_MOUSEHOOKMSG = WM_USER + 1;

var
  GlobalHooksFormHandle: HWND = 0;
  MouseHookHandle: HHOOK = 0;

function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  LMouseHookStruct: TMouseHookStruct;
  LMousePositionX: Integer;
  LMousePositionY: Integer;
begin
  if nCode = HC_ACTION then
  begin
    LMouseHookStruct := PMouseHookStruct(lParam)^;
    LMousePositionX := LMouseHookStruct.pt.X;
    LMousePositionY := LMouseHookStruct.pt.Y;

    if GlobalHooksFormHandle <> 0 then
      SendMessage(GlobalHooksFormHandle, WM_MOUSEHOOKMSG, LMousePositionX, LMousePositionY);
  end;

  Result := CallNextHookEx(MouseHookHandle, nCode, wParam, lParam);
end;

function InstallHooks(AGlobalHooksFormHandle: HWND): Boolean; stdcall;
var
  LMouseHookProc: TFNHookProc;
begin
  GlobalHooksFormHandle := AGlobalHooksFormHandle;

  LMouseHookProc := MouseHookProc;
  MouseHookHandle := SetWindowsHookEx(WH_MOUSE, LMouseHookProc, HInstance, 0);

  Result := MouseHookHandle <> 0;
end;
Habt ihr Ideen, wieso er die Message nicht mehr schickt ??

Falls euch der Code nicht reicht, ich hab mal die ganze Projektgruppe angehängt.

Vielen Dank schon mal im Voraus,
Oliver :hi:

DGL-luke 11. Aug 2006 15:58

Re: Message wird nicht gesendet bei globalem Hook
 
du könntest versuchen, als Nachricht eine mit RegisterWindowMessage erzeugte Nachricht zu benutzen. WM_USER+x wird nur empfohlen, wenn du in deinen threads rumfunkst und nicht zwischen prozessen.

Außerdem solltest du GlobalHooksFormHandle mal protokollieren(in eine datei schreiben z.B.), es könnte sein, dass die nicht immer den richtigen Wert hat. am besten per Broadcast suchen (und dann auf jeden fall mit RegisterWindowMessage).

Broadcasts kommen übrigens nur bei top-level windows an, also im Application.OnMessage!

SirThornberry 11. Aug 2006 16:09

Re: Message wird nicht gesendet bei globalem Hook
 
Genau aus dem Grund nimmt der Author mmf's.

Wenn du einen Hook "installierst" wird die DLL in die verschiedensten Prozesse geladen. Beim laden der DLL in den verschiedenen Prozessen ruft jedoch niemand deine Methode InstallHooks auf. Die Methode InstallHooks wird einzig in der DLL-Instanz geladen welche du in deinem Programm lädst. Wenn deine DLL als in der Explorer.exe geladen wird, wird dort sozusagen nur ein LoadLibrary gemacht und ein lokaler Hook auf deine DLL-Procedure. Es wird bei einem SetWindowsHook-Aufruf also nix anderes gemacht als
- Lade in so ziemlich jedem Prozess die DLL "DeineDLL.DLL" und schleife alle Nachrichten durch die Funktion MouseHookProc der DLL.
Es wird also darin nirgends deine Variable GlobalHooksFormHandle gesetzt, das geschieht einzug und allein in der DLL instanz die du in deinem Programm lädst.

Dir scheint also das Verständnis zu fählen was genau bei einem hook-setzen passiert.

Dein Code kommt ungefähr dem gleich:
Du hast einen Notizblock und schreibst eine Telefonnummer drauf.
Dann sagst du all deinen Freunden Sie sollen sich auch einen Notizblock vom Stabel nehmen und alles was passiert sollen sie telefonisch an die auf dem Block vermerkte Nummer übermitteln. Das Problem: Die telefonnummer steht nur auf deinem Block.

DGL-luke 11. Aug 2006 16:13

Re: Message wird nicht gesendet bei globalem Hook
 
jop, das liegt daran, dass die DLLs nicht den selben speicher benutzen. Ein Feature, das Delphi einfach fehlt. (Liegt das nicht am MemoryManager? Kann das nicht z.B. FastMM?)

SirThornberry 11. Aug 2006 16:17

Re: Message wird nicht gesendet bei globalem Hook
 
@DGL-Luke: Nein, das ist kein Problem vom Delphimemorymanager. Wie bereits geschrieben wird die DLL bei einem Aufruf von SetWindowsHookEx in jedem Prozess neu geladen, so als würde in dem Prozess jemand einen lokalen Hook mit SetWindowsHookEx starten. Ein globaler Hook ist sozusagen ein Rundruf das so ziemlich jeder einen Lokalen Hook auf die Adresse-X in der DLL-X setzen soll. Dabei laden dann die Prozesse die DLL und setzen eben einen lokalen Hook auf die Funktion.

Einziges was es in Delphi nicht gibt (was in C++ wohl einfacher gelöst ist) das es da gemeinsam genutzen Speicher ohne den Umweg über mmf's gibt.

Das ganze ist aber auch logisch, denn wenn die Messages von anderen Prozessen an die Hook-Procedure des geinen Prozesses übergeben werden würden wären die Adressen welche sich teilweise in WParam und LParam befinden völlig nutzlos da die Adressen nur im anderen Prozess gültig sind (also in dem Prozess wo sie her kommen).

idontwantaname 11. Aug 2006 16:19

Re: Message wird nicht gesendet bei globalem Hook
 
Okay, danke :)

Jetzt weiß ich wo mein Problem liegt, und werde einen anderen Weg nehmen.

mfg Oliver

DGL-luke 11. Aug 2006 16:22

Re: Message wird nicht gesendet bei globalem Hook
 
Zitat:

Einziges was es in Delphi nicht gibt (was in C++ wohl einfacher gelöst ist) das es da gemeinsam genutzen Speicher ohne den Umweg über mmf's gibt.
Das meinte ich... dann würde in InstallHook das richtige Handle gesetzt und die anderen könnten es einfach benutzen.

SirThornberry 11. Aug 2006 16:26

Re: Message wird nicht gesendet bei globalem Hook
 
aber eben auch nur wenn die Variable in C++ so speziell deklariert wäre das sie im gemeinsam genutzten speicher liegt. Und dementsprechend kann man das in Delphi durch mmf's auch erreichen.

ich habs bei meinen Programmen wenn ich sowas braucht bisher immer im Hauptprogramm ein mmf angelegt und das Handle rein geschrieben. Die DLL's haben dann beim laden (also zwischen begin und end) das mmf geöffnet und das handle gelesen und dann auch mit sendmessage kommuniziert.

idontwantaname 11. Aug 2006 16:55

Re: Message wird nicht gesendet bei globalem Hook
 
Ich hab's jetzt so gemacht, dass im Ladeabschnitt der DLL per FindWindow mein Handle gesucht wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:48 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