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 Problem mit Nachricht aus DLL (https://www.delphipraxis.net/25474-problem-mit-nachricht-aus-dll.html)

Chris P 7. Jul 2004 10:15


Problem mit Nachricht aus DLL
 
HI Leute,

ich schreibe grade einen Maushook.

Ich lasse mir die Mauskoordinaten aus einer DLL schicken.

In meinem Hauptprogramm habe ich eine Prozedur die die Nachricht verarbeitet.

Aber wie kann ich die x und y Koordinaten anzeigen lassen?

Wo liegt hier der Fehler??

Delphi-Quellcode:
procedure TForm1.DllMessage(var Msg: TMessage);
begin
   case Msg.wParam of
     WM_MOUSEMOVE: begin  Label1.Caption := InttoStr(LOWORD(Msg.lparam));
                           Label2.Caption := InttoStr(HIWORD(Msg.lParam));
                   end;
 end;
end;

Luckie 7. Jul 2004 10:19

Re: Problem mit Nachricht aus DLL
 
Zitat:

Zitat von Chris P
Wo liegt hier der Fehler??

Der Fehler liegt in Zeile 153, da muss es ">" statt "<" heißen. :roll:

Woher sollen wir wissen, wo der Fehler liegt, wenn du uns nicht sagst, wie er sich manifestiert? Irgendwelche Fehlermeldungen, Exceptions oder einfach nur ein ungewünschtes Ergebnis???

Chris P 7. Jul 2004 10:23

Re: Problem mit Nachricht aus DLL
 
Es kommt kein direkter Fehler,

aber in Label1 steht 65244 und in Label2 die Zahl 18.

Die Zahlen verändern sich auch nicht!

Ich bekomme nicht die aktuellen Mauskoordinaten angezeigt.

Christian Seehase 7. Jul 2004 10:27

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

daraus würde ich mal schliessen, dass der Fehler in der DLL liegt.

Chris P 7. Jul 2004 10:29

Re: Problem mit Nachricht aus DLL
 
Hier ist ein Ausschnitt aus der DLL:
Delphi-Quellcode:
function MouseHookFunc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  { Nachricht an Fenster weiterleiten }
  Result := CallNextHookEx(hKeyHook, Code, wParam, lParam);

  { Nachricht auswerten }
  if Code >= 0 then
  begin

        hMap := OpenFileMapping(FILE_MAP_WRITE, False, 'MMF');
        HookRec := MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
        if HookRec <> nil then
           hApp := HookRec.AppHnd;

           SendMessage(hApp, WM_MOUSEHOOK, wparam, lParam);

  end
  else
     Exit;
end;

Christian Seehase 7. Jul 2004 10:34

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

bist Du sicher, dass Du die richtige Stelle erwischt hast?

Code:
WM_MOUSE[color=red][b]MOVE[/b][/color]: begin  Label1.Caption := InttoStr(LOWORD(Msg.lparam));
Code:
SendMessage(hApp, WM_MOUSE[color=red][b]HOOK[/b][/color], wparam, lParam);

Chris P 7. Jul 2004 10:38

Re: Problem mit Nachricht aus DLL
 
Ich denke schon.

Die Prozedur DLLMessage ist ja in meinem Hauptprog. und das andere ist in der DLL.

Chris P 7. Jul 2004 10:41

Re: Problem mit Nachricht aus DLL
 
Die DLLMessage ist wie folgt deklariert:
Delphi-Quellcode:
procedure DllMessage(var Msg: TMessage); message WM_MOUSEHOOK;
In Msg.wParam könnte ja zB: WM_MOUSEMOVE drin stehen.

Christian Seehase 7. Jul 2004 10:41

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

es wäre nur ganz praktisch wenn die Messages auch die gleichen wären.

Christian Seehase 7. Jul 2004 10:43

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

sorry, da hab' ich nicht aufgepasst.
Das WM_MOUSEMOVE als wParam übergeben wird, und nicht als Message hatte ich übersehen :oops:

Chris P 7. Jul 2004 10:44

Re: Problem mit Nachricht aus DLL
 
Ich schicke meine eigene Message namens WM_MOUSEHOOK an mein Prog.

In dem wParam dieser Message steht dann wiederum zB. WM_MOUSEMOVE.

Chris P 7. Jul 2004 10:51

Re: Problem mit Nachricht aus DLL
 
Aber wo könnte nun der Fehler liegen?

Christian Seehase 7. Jul 2004 10:52

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

schreib' doch mal, zum Testen, einen festen Wert in lParam, wenn WM_MOUSEMOVE von der DLL gesendet werden soll.

Chris P 7. Jul 2004 10:57

Re: Problem mit Nachricht aus DLL
 
Ich hab jetzt mal als lParam die Konstante 20 geschickt und die wird ohne Fehler übergeben und angezeigt.

Aber wie funktioniert das jetzt mit den Mousekoords?

Muss lParam da nicht irgendwas mit PMOUSEHOOKSTRUCT sein oder?

neolithos 7. Jul 2004 11:02

Re: Problem mit Nachricht aus DLL
 
Ersten:

Schließe in der Hook das Filemapping-Object sauber.

Zweitens:

lParam bei einer MouseHook ist vom Typ PMouseHookStruct.
Delphi-Quellcode:
procedure TForm1.DllMessage(var Msg: TMessage);
begin
  case Msg.wParam of
       WM_MOUSEMOVE:
         with PMouseHookStruct(Msg.lParam)^ do
           begin  
             Label1.Caption := InttoStr(pt.x);
             Label2.Caption := InttoStr(pt.y);
           end;
  end;
end;

Christian Seehase 7. Jul 2004 11:06

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

wenn lParam die Adresse einer Datenstruktur ist, musst Du diese natürlich auch als Adresse verwenden:

Delphi-Quellcode:
var
  MouseHook : PMOUSEHOOKSTRUCT;

begin
  MouseHook := PMOUSEHOOKSTRUCT(msg.lParam);
  case Msg.wParam of
     WM_MOUSEMOVE: begin  Label1.Caption := InttoStr(MouseHook^.pt.x);
                           Label2.Caption := InttoStr(MouseHook^.pt.y);
                   end;
end;

Chris P 7. Jul 2004 11:16

Re: Problem mit Nachricht aus DLL
 
Deine Lösung sieht gut aus, aber hat meinen PC zweimal abschmieren lassen sodass ich einen Neustart machen musste. Wodran liegt dass?

Christian Seehase 7. Jul 2004 11:23

Re: Problem mit Nachricht aus DLL
 
Moin Chris,

ich hab' mir das mal, auf die Schnelle, so gefakt:

Delphi-Quellcode:
procedure TForm1.DllMessage(var Msg: TMessage);

var
  MouseHook : PMOUSEHOOKSTRUCT;

begin
  MouseHook := PMOUSEHOOKSTRUCT(msg.lParam);
  case Msg.wParam of
     WM_MOUSEMOVE: begin  Label1.Caption := InttoStr(MouseHook^.pt.x);
                           Label2.Caption := InttoStr(MouseHook^.pt.y);
                   end;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);

var
  msg      : TMessage;
  MouseHook : MOUSEHOOKSTRUCT;

begin
  MouseHook.pt.x := 100;
  MouseHook.pt.y := 200;
  msg.WParam := WM_MOUSEMOVE;
  msg.LParam := lParam(@MouseHook);
  DLLMessage(msg);
end;
Funktioniert allerbest.

Hast Du lParam in der DLL auch wieder korrigiert, so dass es die Adresse enthält?

Chris P 7. Jul 2004 11:34

Re: Problem mit Nachricht aus DLL
 
Ist das korrekt so?
Delphi-Quellcode:
 SendMessage(hApp, WM_MOUSEHOOK, wparam, lParam);
Der PC stürzt immer noch ab :cry:

neolithos 7. Jul 2004 11:58

Re: Problem mit Nachricht aus DLL
 
Nein das ganze geht so nicht!
Grund: Der Speicher auf, die die Adresse zeigt gibt es in deinem Process nicht.

neolithos 7. Jul 2004 12:04

Re: Problem mit Nachricht aus DLL
 
Meine Mouse-Hook:

Delphi-Quellcode:
  PHookData = ^THookData;
  THookData = packed record
    hk,
    hWnd,
    wmNotify : Cardinal;
  end;
Delphi-Quellcode:
function MouseHook(iCode : Integer; dwMsg : Cardinal; pMouseData : PMouseHookStruct) : Integer;
var pData : PHookData;
    hMap : Cardinal;
    pt : TSmallPoint;
begin
  hMap := OpenFileMapping(FILE_MAP_ALL_ACCESS, false, csFileMappingMouse);
  if hMap = 0 then
     Result := 0
  else
     begin
       pData := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);

       if (iCode = HC_ACTION) then
          if pData^.hWnd <> 0 then
             begin
               pt := PointToSmallPoint(pMouseData^.pt);
               PostMessage(pData^.hWnd, pData^.wmNotify, dwMsg, PCardinal(@pt)^);
             end;

       Result := CallNextHookEx(pData^.hk, iCode, dwMsg, Integer(pMouseData));
       UnmapViewOfFile(pData);
       CloseHandle(hMap);
     end;
end;

Chris P 7. Jul 2004 12:30

Re: Problem mit Nachricht aus DLL
 
@neolithos:

Könntest du mir bitte deinen kompletten Moushook geben?

Das wäre sehr hilfreich..
Danke

neolithos 7. Jul 2004 12:52

Re: Problem mit Nachricht aus DLL
 
Zum Registrieren:

Delphi-Quellcode:
var hMap : Cardinal = 0;
    hLib : Cardinal = 0;

procedure RegisterMouseHook(hWnd, wmNotify : Cardinal);
var pData : PHookData;
    proc : Pointer;
begin
  if hMap = 0 then
     try
       hLib := LoadLibrary('Hk.dll');
       if hLib = 0 then
          raise Exception.Create('Hk.dll nicht gefunden.');

       proc := GetProcAddress(hLib, 'MouseHook');
       if proc = nil then
          raise Exception.Create('Hook-Procedure nicht gefunden.');

       hMap := CreateFileMapping(0, nil, PAGE_READWRITE, 0, SizeOf(THookData), csFileMappingMouse);
       if hMap = 0 then
          raise Exception.Create('Filemapping fehlgeschlagen');

       pData := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
       pData^.hWnd := hWnd;
       pData^.wmNotify := wmNotify;
       pData^.hk := SetWindowsHookEx(WH_MOUSE, proc, hLib, 0);
       if pData^.hk = 0 then
          raise Exception.Create('Hook konnte nicht installiert werden.');

       UnmapViewOfFile(pData);
     except
       FreeLibrary(hLib);
       CloseHandle(hMap);
       raise;
     end;
end;

procedure UnRegisterMouseHook;
var pData : PHookData;
begin
  if hMap <> 0 then
     begin
       pData := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
       UnhookWindowsHookEx(pData^.hk);
       UnmapViewOfFile(pData);
       FreeLibrary(hLib);
       CloseHandle(hMap);
       hMap := 0;
     end;
end;

neolithos 7. Jul 2004 12:54

Re: Problem mit Nachricht aus DLL
 
In der Anwendung:
Delphi-Quellcode:
  TMouseHookMsg = packed record
    dwMsg,
    dwMouseMsg : Cardinal;
    pt : TSmallPoint;
  end;
Delphi-Quellcode:
  TForm1 = ....
    procedure WMMouseNotify(var Message : TMouseHookMsg); message WM_APP + 11;
....
Delphi-Quellcode:
procedure TfrmMain.WMMouseNotify(var Message: TMouseHookMsg);
begin
  with Message do
    Label4.Caption := Format('x: %d y: %d', [pt.x, pt.y]);
end;
Delphi-Quellcode:
constructor TForm1.Create(fOwner: TComponent);
begin
  inherited;
  RegisterMouseHook(Handle, WM_APP + 11);
end;

destructor TForm1.Destroy;
begin
  UnRegisterMouseHook;
  inherited;
end;

Chris P 7. Jul 2004 14:59

Re: Problem mit Nachricht aus DLL
 
Ich habe jetzt eine Lösung gefunden die einigermaßen läuft:
Delphi-Quellcode:
function MouseHookFunc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
   Mousespos: MOUSEHOOKSTRUCT;
begin
  //Nachricht an Fenster weiterleiten
    Result := CallNextHookEx(hMouseHook, Code, wParam, lParam);

  // Nachricht auswerten
  if Code >= 0 then
  begin

        hMap := OpenFileMapping(FILE_MAP_WRITE, False, 'MMF');
        HookRec := MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
        if HookRec <> nil then
           hApp := HookRec.AppHnd;
       
          Mousepos.pt := Mouse.CursorPos;

       SendMessage(hApp, WM_MOUSEHOOK, wparam, Integer(@Mousepos));
       UnmapViewOfFile(HookRec);
       CloseHandle(hMap);
  end
  else
     Exit;

end;
Aber sobald ich mit dem Mauszeiger aus meinem Programm gehe kommt eine Fehlermeldung
und zwar eine Zugriffsverletzung in meiner EXE. Woran könnte das liegen?

neolithos 7. Jul 2004 15:51

Re: Problem mit Nachricht aus DLL
 
Das hatte ich schon mal gesagt!

Diese Adresse gibt es nicht mehr!

Grund: deine Hook wurde in einen anderen Adress-Space aufgerufen. Dieser hat andere Adressen! Die in deinem Programm nicht gültig sind.

Schau die genau an was ich gemacht habe!

Will man mehr als 4 Byte übertragen, muss entweder ein FileMapping oder eine Pipe eingerichtet werden.

Achte dabei aber darauf, dass Windows ein Multi-Prozess OS ist.

Chris P 8. Jul 2004 06:41

Re: Problem mit Nachricht aus DLL
 
@Neolithos

1. Welche Adresse meinst du?

2. An welcher Stelle bekommst du denn die aktuellen Mauskoords in deinem Hook?

Muetze1 8. Jul 2004 08:52

Re: Problem mit Nachricht aus DLL
 
Moin!

Zu 1.:
Code:
       SendMessage(hApp, WM_MOUSEHOOK, wparam, Integer(@Mousepos));
Integer(@Mousepos) meint er - du verschickst hier die Adresse der Mauspos Struktur - die auch ohne DLL/App ungültig wäre, da du die Adresse einer lokalen Variable verschickst - und die ist eh ungültig nach verlassen der Funktion.

MfG
Muetze1

TStringlist 8. Jul 2004 15:55

Re: Problem mit Nachricht aus DLL
 
@Chris P

Bei einem globalen Hook gilt, dass die DLL (also auch die Variablen darin oder Ptr auf diese Variablen) dann fast immer im Adressraum einer jeweils fremden Application untergebracht ist. Dementsprechend haben von dort verschickte Adressen dann in deinem eigenen Prog natürlich keine Gültigkeit mehr (weil doch jede Appllication ihren ganz 'persönlichen' eigenen Adressraum hat).

Nur dann, wenn diejenige HookProc aktiv ist, die beim Erstellen deines globalen Hooks dann auch im Adressraum deines aktuellen Programmes aufgebaut wurde, ..nur dann event. könnte so ein Pointer auch dementsprechend überhaupt brauchbar sein (also nur wenn die Maus gerade über deiner Form1 ist ..wie das ja bei dir der Fall war).

Da man für eine Mitteilung von X/Y-Screen-Koordinaten wohl immer nur 2*2 Bytes benötigen wird, könntest du diese aber z.B. auch über den LParam direkt verschicken:

Code:
var X,Y : Word;
...
      X := PMouseHookStruct(lParam)^.pt.x;
      Y := PMouseHookStruct(lParam)^.pt.y;
      PostMessage(HookRec^.AppHnd, WM_MOUSEHOOK, wp, X*65536 + Y);

edit: lp --> lParam / war 'ne eigene Kurzfassung zum schnelleren Austesten

Muetze1 8. Jul 2004 20:12

Re: Problem mit Nachricht aus DLL
 
Moin!

Zitat:

Zitat von TStringlist
edit: lp --> lParam / war 'ne eigene Kurzfassung zum schnelleren Austesten

Jo, weil es ja MakeWParam() und MakeLParam() gibt...

MfG
Muetze1

TStringlist 8. Jul 2004 20:43

Re: Problem mit Nachricht aus DLL
 
Wieso? wenn ich das ganze mit MakeLParam() ausschreiben muss, dann brauche ich trotzdem immer noch mindestens 4 ganze Anschläge mehr. Ergo: Etwas schneller, und was anderes schrieb ich ja auch nicht, ist immer noch meine Version.

Gut, MakeWParam() etc. mag es auch noch geben, aber bei deiner versuchten Verknüpfung von beidem bleibt doch nur noch mehr der Gedanke:


..immer diese wahrhaft großen Lehrer der Menschheit und ihren glorreichen Formulierungen & Effekthaschereien! Gott möge sie segnen!

*g*

Chris P 9. Jul 2004 11:48

Re: Problem mit Nachricht aus DLL
 
Ich habe das jetzt so gemacht wie Neolithos:

Delphi-Quellcode:
function MouseHookFunc(Code: Integer; dwmsg: Cardinal; pMousedata: PMOUSEHOOKSTRUCT): LRESULT; stdcall;
var
   pt : TSmallPoint;
begin
  // Nachricht auswerten
  if Code >= 0 then
  begin

        hMap := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MMF');
        HookRec := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        if HookRec <> nil then
        begin
           pt := PointToSmallPoint(pMousedata^.pt);
           PostMessage(HookRec.AppHnd, WM_MOUSEHOOK, dwmsg, PCardinal(@pt)^);
        end;
       UnmapViewOfFile(HookRec);
       CloseHandle(hMap);
  end
  else
     Exit;
  //Nachricht an Fenster weiterleiten
    Result := CallNextHookEx(hMouseHook, Code, dwmsg, Integer(pMousedata));
end;
Aber in der Zeile mit POSTMESSAGE kommt eine Fehlermeldung:

"Operator oder Semikolon fehlt"

Wo liegt der Fehler?

@neolithos:

Wie sieht deine Projektdatei aus??

TStringlist 9. Jul 2004 12:20

Re: Problem mit Nachricht aus DLL
 
wenn du die PostMessage-Zeile so schreibst:

Code:
PostMessage(HookRec.AppHnd, WM_MOUSEHOOK, dwmsg, integer(pt));
müsste sie stimmen. Darin sollte also nun kein Pointer mehr auf irgendwelche Koordinatenwerte enthalten sein, sondern eben nur noch mehr der eigentliche Koordinatenwert selbst.

neolithos 9. Jul 2004 13:24

Re: Problem mit Nachricht aus DLL
 
@Chris P:
Du hast eine PM.

Mit meinem Project.

Chris P 12. Jul 2004 08:02

Re: Problem mit Nachricht aus DLL
 
@Neolithos:

Vielen Dank.

Der Hook ist sehr gut!!!


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