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 Nachrichten vollkommen abfangen (https://www.delphipraxis.net/41987-nachrichten-vollkommen-abfangen.html)

OrallY 11. Mär 2005 16:40


Nachrichten vollkommen abfangen
 
Hi,

ist es möglich eine Nachricht, die an eine fremde Anwendung geschickt wird, abzufangen und zu verhindern, dass die Nachricht die Anwendung erreicht?

Hintergrund der Frage ist das Problem, dass ich gerne Mousemove-Messages abfangen möchte, da diese zu unliebsamen Neuzeichnungen einiger Controls führt. Zwar habe ich schon versucht die Mousemove-Nachrichten mit einem LLMouseHock abzufangen, jedoch hat dies zur Folge, dass die Maus einfach stehen bleibt.

Vielleicht hätte jemand noch einen anderen Vorschlag, wie ich verhindern kann, dass sich einige Controls wegen Highlighting neuzeichnen. Ich arbeite zur Zeit an einem Programm, das direkt auf den Desktop zeichnet. Wird nun ein solcher Highlight aktiv und das Control neugezeichnet, entstehen beim löschen des Gemalten Artefakte (gemalte und gelöscht wird mit dem selben Inverse-Pen).

Ich habe auch schon ausprobiert, die Steuerelemnte einfach für den Zeitraum, wo sich die Maus über sie bewegt zu deaktivieren, jedoch bleibt zum einen beispielsweise das Osziloskop von Winamp stehen. Außerdem ist es doch reichlich ärgerlich, wenn das Programm aus irgendwelchen Grünen absürtzen sollte und deaktivierte Controls zurücklässt.

Eine andere Idee war ein transparentes Fenster, dass ich über den Bildschirm lege und dann dort drauf zeichne. Jedoch führte dies zu Darstellungsproblemen mit meiner TV-Software und teilweise flackerte der Bildschirm, wenn ich das Fenster wieder versteckte.

Vielen Dank im Vorraus

greez

Mephistopheles 26. Mär 2005 14:14

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von OrallY
ist es möglich eine Nachricht, die an eine fremde Anwendung geschickt wird, abzufangen und zu verhindern, dass die Nachricht die Anwendung erreicht?

Hooks oder DLL-Injection mit Subclassing. Also ja.

Zitat:

Zitat von OrallY
Hintergrund der Frage ist das Problem, dass ich gerne Mousemove-Messages abfangen möchte, da diese zu unliebsamen Neuzeichnungen einiger Controls führt. Zwar habe ich schon versucht die Mousemove-Nachrichten mit einem LLMouseHock abzufangen, jedoch hat dies zur Folge, dass die Maus einfach stehen bleibt.

Reicht nicht ein normaler Maushook auch? Also ohne LL?

Zitat:

Zitat von OrallY
Vielleicht hätte jemand noch einen anderen Vorschlag, wie ich verhindern kann, dass sich einige Controls wegen Highlighting neuzeichnen. Ich arbeite zur Zeit an einem Programm, das direkt auf den Desktop zeichnet. Wird nun ein solcher Highlight aktiv und das Control neugezeichnet, entstehen beim löschen des Gemalten Artefakte (gemalte und gelöscht wird mit dem selben Inverse-Pen).

Zeichnest du während einer Mausaktion? Dann wäre vermutlich Mousecapturing was für dich. Dabei werden z.B. die Fenster über welche du hoverst keine Mausnachrichten erhalten, denn beim Mousecapturing bekommst du alle Mausnachrichten.

Zitat:

Zitat von OrallY
Eine andere Idee war ein transparentes Fenster, dass ich über den Bildschirm lege und dann dort drauf zeichne. Jedoch führte dies zu Darstellungsproblemen mit meiner TV-Software und teilweise flackerte der Bildschirm, wenn ich das Fenster wieder versteckte.

Das sollte klar werden, wenn man weiß, daß es neben der guten alten GDI ja auch noch DirectDraw usw. gibt.

OrallY 26. Mär 2005 15:13

Re: Nachrichten vollkommen abfangen
 
Erstmal vielen Dank für die Antwort. Ich hatte die Hoffnung schon aufgegeben :wink:.

Zitat:

Zitat von Mephistopheles
Hooks oder DLL-Injection mit Subclassing. Also ja.

Könntest du das bitte genauer erläutern?

Zitat:

Zitat von Mephistopheles
Reicht nicht ein normaler Maushook auch? Also ohne LL?

Wenn man es so macht wie ich, dann nein. Meine Vorgehensweise bisher war, einen LowLevel-MouseHook zu erstellen und durch Nichtaufruf von CallNextHookEx die Mausnachrichten daran zu hindern, an weitere Fenster weitergeleitet zu werden.
Meiner Meinung nach eine schlechte Lösung, auf die ich leider aus Ermangelung weitere Lösungen zurückgreifen musste :|.

Zitat:

Zitat von Mephistopheles
Zeichnest du während einer Mausaktion? Dann wäre vermutlich Mousecapturing was für dich. Dabei werden z.B. die Fenster über welche du hoverst keine Mausnachrichten erhalten, denn beim Mousecapturing bekommst du alle Mausnachrichten.

Das ist schon mal ein sehr guter Hinweis! thx. Allerdings funktioniert das Mousecapturing ja nur, wenn ich die Maus innerhalb des eigenen Fensters drücke, nicht aber, wenn außerhalb gedrückt wird. Deshalb ja auch der LL-Mousehook, da der Anwender überall zu zeichnen anfangen können soll. (Zumal meine Anwendung nur ein Messageonly-Window besitzt).

Also wäre das Abfangen von Mausklicks außerhalb des Clientbereichs mittels DLL-Injection mit Subclassing (was immer das auch sein mag) möglich? Wenn ja, wie? Und wie ginge es mit Hooks? (Fragen über Fragen :mrgreen:).

greez

Chewie 26. Mär 2005 15:56

Re: Nachrichten vollkommen abfangen
 
Also was Subclassing ist, erfährst du in den ersten Kapiteln von Luckies Winapi-Tutorials.
Nur erfährst du da halt nicht, wie du deinen Code in den Prozess überhaupt erst reinkriegst ;)

Mephistopheles 26. Mär 2005 20:10

Re: Nachrichten vollkommen abfangen
 
Die Zeit is kurz, die Kunst ist lang.

Subclassing würde dir erlauben tatsächlich von einem Fenster die Mausnachrichten verhindern. Allerdings bliebe das Problem, daß dieses "Fenster" ja herausfinden muß, ab wann es wieder Mausnachrichten empfangen darf.

Mich würde erst einmal interessieren, was genau du erreichen möchtest, denn dies wäre hier wohl besser. Ich habe noch nicht einmal deinen aktuellen Lösungsansatz komplett deiner Beschreibung entnehmen können. Hingegen zu einer bestimmten Problemstellung kann man eventuell Alternativen finden.

c113plpbr 26. Mär 2005 20:28

Re: Nachrichten vollkommen abfangen
 
Ich weis nicht genau um was es genau geht, aber wenn du das versenden von WindowMessages verhindern willst, könnte dir da ein Globaler API-Hook auf die SendMessageA & SendMessageW funktionen vielleicht weiterhelfen.

Um herauszufinden, wann die Messages abgefangen werden müssen, und wann nicht, könnte man einen Globalen Mutex verwenden.

All dies ist eigentlich relativ einfach zu realisieren, mit Hilfe einer Library: MadCodeHook
Die MadCodeHook library gibt es unter http://www.madshi.net/ für nichtkommerzielle Zwecke kostenlos zum Download.

ciao, Philipp

Mephistopheles 26. Mär 2005 20:51

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von c113plpbr
All dies ist eigentlich relativ einfach zu realisieren, mit Hilfe einer Library: MadCodeHook
Die MadCodeHook library gibt es unter http://www.madshi.net/ für nichtkommerzielle Zwecke kostenlos zum Download.

Und sehr instabil (bezieht sich nur auf das besagte Produkt!).

Und schonmal geguckt wie oft diese APIs so durchschnittlich aufgerufen werden? Da tut jeder zusätzliche CPU-Zyklus weh. Aua.

c113plpbr 26. Mär 2005 21:12

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von Mephistopheles
Zitat:

Zitat von c113plpbr
All dies ist eigentlich relativ einfach zu realisieren, mit Hilfe einer Library: MadCodeHook
Die MadCodeHook library gibt es unter http://www.madshi.net/ für nichtkommerzielle Zwecke kostenlos zum Download.

Und sehr instabil (bezieht sich nur auf das besagte Produkt!).

Keineswegs. Bisher hat noch alles problemlos funktioniert, was ich damit gemacht habe!

Zitat:

Zitat von Mephistopheles
Und schonmal geguckt wie oft diese APIs so durchschnittlich aufgerufen werden? Da tut jeder zusätzliche CPU-Zyklus weh. Aua.

Ja, schon klar, aber Windowseigene Methoden tun nichts anderes. Nur eben auf Systemwegen.
Und, zur Geschwindigkeit: Ein DirectX-Hook (wie er z.B. in Fraps verwendet wird), der vllt. noch die ein oder andere Funktion aufruft, kostet vielleicht 2 Frames (bei ner durchschnittlichen Framerate von 60fps). Und das ist nun wirklich wenig ... und nun sag mir nicht, dass diese SendMessage-Funktionen dauerhaft öfter als 60 mal pro sekunde aufgerufen werden!

[edit]
Achja, die Entwickler von Detours (ist sowas ähnliches, nur von M$) haben den Zeitunterschied (bei leeren Funktionen) mal nachgemessen:
Direktaufruf: 113 ns
Mit Detours: 145 ns
und das ist sogut wie nichts ...
[/edit]

ciao, Philipp

Mephistopheles 26. Mär 2005 21:23

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von c113plpbr
Keineswegs. Bisher hat noch alles problemlos funktioniert, was ich damit gemacht habe!

Ist das repräsentativ? Bei mir war bereits das Gegenteil der Fall.

Zitat:

Zitat von c113plpbr
Ja, schon klar, aber Windowseigene Methoden tun nichts anderes. Nur eben auf Systemwegen.
Und, zur Geschwindigkeit: Ein DirectX-Hook (wie er z.B. in Fraps verwendet wird), der vllt. noch die ein oder andere Funktion aufruft, kostet vielleicht 2 Frames (bei ner durchschnittlichen Framerate von 60fps). Und das ist nun wirklich wenig ... und nun sag mir nicht, dass diese SendMessage-Funktionen dauerhaft öfter als 60 mal pro sekunde aufgerufen werden!

Das kommt immer auf die Menge von Fenstern an. Prinzipiell magst du recht haben. Aber an welcher Prozessorleistung (CPU + GPU) hast du denn die 2 FPS gemessen? Ich denke mal an meinem K6-II 450 (16 MB Grafikkarte) war es nicht, oder? Und ja - auch wenn Entwicklerrechner oft sehr leistungsfähig sind - die meisten Rechner kommen nicht an einen Pentium HT ran.

Zitat:

Zitat von c113plpbr
[edit]
Achja, die Entwickler von Detours (ist sowas ähnliches, nur von M$) haben den Zeitunterschied (bei leeren Funktionen) mal nachgemessen:
Direktaufruf: 113 ns
Mit Detours: 145 ns
und das ist sogut wie nichts ...
[/edit]

LOL - und wieder die Frage nach dem Rechner. Außerdem ist hier die Quantität der Aufrufe ganz offensichtlich sehr entscheidend. Und SendMessage() dürfte zu den häufigsten Funktionen gehören.

c113plpbr 26. Mär 2005 21:28

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von Mephistopheles
Ist das repräsentativ? Bei mir war bereits das Gegenteil der Fall.

Dann hast du wohl etwas falsch gemacht ...

Zitat:

Zitat von Mephistopheles
Das kommt immer auf die Menge von Fenstern an. Prinzipiell magst du recht haben. Aber an welcher Prozessorleistung (CPU + GPU) hast du denn die 2 FPS gemessen? Ich denke mal an meinem K6-II 450 (16 MB Grafikkarte) war es nicht, oder? Und ja - auch wenn Entwicklerrechner oft sehr leistungsfähig sind - die meisten Rechner kommen nicht an einen Pentium HT ran.

(es war ja nur ein beispiel) Siehe mein Nachtrag.

[edit]
Man, warum musst du alles, was ich sage so kritisieren, als ob ich überhaupt keine ahnung hätte?
bisher hab ich von dir nur behauptungen gehört, keine beweise. Beweise hab ich ja schon (im gegensatz zu dir) versucht aufzubringen ...

Zitat:

Zitat von Mephistopheles
LOL - und wieder die Frage nach dem Rechner. Außerdem ist hier die Quantität der Aufrufe ganz offensichtlich sehr entscheidend. Und SendMessage() dürfte zu den häufigsten Funktionen gehören.

Und selbst wenn 1000 aufrufe pro sekunde kämen (was relativ unwarscheinlich ist), wäre api hooking nicht viel langsamer als windowseigene methoden.
Aber ich habe nie behauptet, dass dies die "ultimative lösung" ist, es war nur ein vorschlag. Und welchen weg OrallY hinterher geht, bleibt doch wohl noch ihm überlassen.
[/edit]

ciao, Philipp

Mephistopheles 26. Mär 2005 23:15

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von c113plpbr
Zitat:

Zitat von Mephistopheles
Ist das repräsentativ? Bei mir war bereits das Gegenteil der Fall.

Dann hast du wohl etwas falsch gemacht ...

Oh. Danke für den Tip, das wußte ich nicht.
Es ist so schwer den falschen Weg zu meiden;
Eine gesunde Einstellung für einen Entwickler ... wenn mein Programm beim Benutzer abstürzt "hat der Benutzer wohl was falsch gemacht".
Mag sein, daß es damals noch nicht funktionierte (es ist schon einige Zeit her). Aber dennoch sollte ein solches Paket immer stabilstmöglich laufen.

Zitat:

Zitat von c113plpbr
Zitat:

Zitat von Mephistopheles
Das kommt immer auf die Menge von Fenstern an. Prinzipiell magst du recht haben. Aber an welcher Prozessorleistung (CPU + GPU) hast du denn die 2 FPS gemessen? Ich denke mal an meinem K6-II 450 (16 MB Grafikkarte) war es nicht, oder? Und ja - auch wenn Entwicklerrechner oft sehr leistungsfähig sind - die meisten Rechner kommen nicht an einen Pentium HT ran.

(es war ja nur ein beispiel) Siehe mein Nachtrag.

Ich brauche ca. 30 Minuten von mir bis zur Arbeit. Jetzt die Quizfrage: welches Fahrzeug benutze ich (oder überhaupt eines?), mit welcher Durchschnittsgeschwindigkeit bewege ich mich fort und welche Entfernung lege ich dabei zurück?
Wie du vielleicht siehst, ist dein Beispielvergleich sinnlos ohne die Rahmendaten.
Genauso sinnlos wie vermeintliche Optimierungen von diversen Assemblerprogrammierern.

Zitat:

Zitat von c113plpbr
[edit]
Man, warum musst du alles, was ich sage so kritisieren, als ob ich überhaupt keine ahnung hätte?
bisher hab ich von dir nur behauptungen gehört, keine beweise. Beweise hab ich ja schon (im gegensatz zu dir) versucht aufzubringen ...

Ich bin der Geist der stets verneint!
Und das mit Recht: denn alles, was entsteht,
ist werth, daß es zu Grunde geht.

Da du Kritik offenbar nicht als konstruktiv (du könntest ja die Rahmendaten nennen) auffassen kannst, verbleibe ich mit besten Grüssen.

Zitat:

Zitat von c113plpbr
Und selbst wenn 1000 aufrufe pro sekunde kämen (was relativ unwarscheinlich ist), wäre api hooking nicht viel langsamer als windowseigene methoden.
Aber ich habe nie behauptet, dass dies die "ultimative lösung" ist, es war nur ein vorschlag. Und welchen weg OrallY hinterher geht, bleibt doch wohl noch ihm überlassen.
[/edit]

Tut es. Habe auch nichts anderes behauptet.
Das mit der Geschwindigkeit hängt aber nach wie vor von den Rahmenbedingungen ab. Aber wie ich sehe renne ich damit gegen massive Wände. Nichtsdestotrotz ist Hooking, sei es nun SSDT-Hooking oder eben API-Hooking im Usermode eine potentiell riskante Sache. Ein PC ist ein sehr universelles Gerät mit reichhaltiger Softwareauswahl. Wie willst du garantieren, daß deine Software mit allen sauber interagiert *). Und vor allem, warum willst du nicht die windowseigenen und damit offiziell unterstützten (und potentiell sichereren) Methoden (Message-Hooks WH_* z.B.) Methoden einem API-Hook vorziehen?
Ja, ein API-Hook mag irrelevant sein. Woher nimmst du aber die Annahme, daß dein Programm das einzige wäre, welches eine bestimmte API hookt?

*) Wenn ein Programm - sagen wir MS Word - abstürzt, nachdem dein Programm installiert wurde; und wenn dies passiert, weil bei Word getrickst wurde (dein Programm sei also nicht schuld für mein Besipiel) - glaubst du im Ernst, daß man Word deshalb runterwerfen und die Schuld geben würde?

c113plpbr 27. Mär 2005 00:45

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von Mephistopheles
Eine gesunde Einstellung für einen Entwickler ... wenn mein Programm beim Benutzer abstürzt "hat der Benutzer wohl was falsch gemacht".

Du drehst mir die Worte im Mund um. So war das nicht gemeint.
Denn wenn du das Programm geschrieben hast, war es wohl nicht des Benutzers Schuld.

Zitat:

Zitat von Mephistopheles
Mag sein, daß es damals noch nicht funktionierte (es ist schon einige Zeit her). Aber dennoch sollte ein solches Paket immer stabilstmöglich laufen.

Willst du damit sagen, dass alles was du programmierst, auf anhieb perfekt funktioniert? Irren ist nun mal Menschlich, und jeder macht Fehler. Aber Fehler kann man ausbessern, und so sollte man jedem die Chance geben, seine Fehler auszubessern, bevor man über ihn, oder sein Werk richtet.
Vielleicht läuft es ja nun stabil, zumindest bin ich der Meinung.

Zitat:

Zitat von Mephistopheles
Ich brauche ca. 30 Minuten von mir bis zur Arbeit. Jetzt die Quizfrage: welches Fahrzeug benutze ich (oder überhaupt eines?), mit welcher Durchschnittsgeschwindigkeit bewege ich mich fort und welche Entfernung lege ich dabei zurück?
Wie du vielleicht siehst, ist dein Beispielvergleich sinnlos ohne die Rahmendaten.
Genauso sinnlos wie vermeintliche Optimierungen von diversen Assemblerprogrammierern.

Damit du es dir auch ausrechnen kannst: 6 Zyklen muss deine CPU (bei einer leeren funktion) mehr schuften. (laut Detours)
Natürlich ist hier nichts anderes miteinberechnet, was getan werden müsste, dass die ganze Aktion auch sinnvoll ist.
Ich will damit eigentlich nur sagen: auch ein Windows-Hook verbrät (mind.) soviel, wie ein API Hook. Daher sind API-Hook und Windows-Hook von der Performance her gleich einzustufen.

Zitat:

Zitat von Mephistopheles
Da du Kritik offenbar nicht als konstruktiv (du könntest ja die Rahmendaten nennen) auffassen kannst, verbleibe ich mit besten Grüssen.

Die Rahmendaten von der Detours Zeitmessung kann ich dir leider nicht nennen, da ich sie nicht besitze, so leid es mir tut. (Nun, man könnte natürlich das Verhältnis der beiden Werte ausrechnen, und es auf einen durchschnittsrechner aus dem Jahre 1999 beziehen ('99 wurde dieses Dokument verfasst), und es dann auf das schlecht-, bzw. bestmögliche auslegen, doch es wird warscheinlich ein Wert bleiben, der vernachlässigbar klein ist. Und wenn nicht, werden Systemeigene Methoden trotzdem kaum schneller sein können.)
Zu meiner "Messung": Wie schon aus meiner Aussage hervorgeht, hab ich dies nicht gemessen, sondern geschätzt.

Zitat:

Zitat von Mephistopheles
Das mit der Geschwindigkeit hängt aber nach wie vor von den Rahmenbedingungen ab. Aber wie ich sehe renne ich damit gegen massive Wände. Nichtsdestotrotz ist Hooking, sei es nun SSDT-Hooking oder eben API-Hooking im Usermode eine potentiell riskante Sache. Ein PC ist ein sehr universelles Gerät mit reichhaltiger Softwareauswahl. Wie willst du garantieren, daß deine Software mit allen sauber interagiert *). Und vor allem, warum willst du nicht die windowseigenen und damit offiziell unterstützten (und potentiell sichereren) Methoden (Message-Hooks WH_* z.B.) Methoden einem API-Hook vorziehen?
Ja, ein API-Hook mag irrelevant sein. Woher nimmst du aber die Annahme, daß dein Programm das einzige wäre, welches eine bestimmte API hookt?

Wie gesagt, ich habe nie behauptet, dass es die beste Methode ist. Aber es sollte ein Vorschlag sein. Ob man diesen nun "ernst" nimmt, oder nicht, überlasse ich jedem selbst.

ciao, Philipp

Christian Seehase 27. Mär 2005 01:35

Re: Nachrichten vollkommen abfangen
 
Moin ihr Beiden,

ich möchte doch dringend darum bitten wieder zum Thema zu kommen, und die begonnene Diskussion ggf. in einem anderen Thread fortzuführen.
Danke.

Falls ihr wollt, kann dieser Thread auch geteilt werden, und als Basis für einen neuen dienen.
Dann bitte per PN melden.

OrallY 27. Mär 2005 13:11

Re: Nachrichten vollkommen abfangen
 
Danke für die rege Beteiligung :wink:.

Zitat:

Zitat von Mephistopheles
Mich würde erst einmal interessieren, was genau du erreichen möchtest, denn dies wäre hier wohl besser. Ich habe noch nicht einmal deinen aktuellen Lösungsansatz komplett deiner Beschreibung entnehmen können. Hingegen zu einer bestimmten Problemstellung kann man eventuell Alternativen finden.

Ein berechtigter Einwandt, dem ich hiermit nachgehen möchte:
  • Programmfunktion:
    Der Benutzer soll im Endeffekt (genaue Funktion ist irrelevant) überall auf dem Bildschirm mit gedrückter rechter Maustaste zeichnen können. Die Anwendung selbst läuft im Hintergrund und soll den Dienst bereitstellen.
  • Problem:
    Drückt man irgendwo auf dem Bildschirm die Maustaste, erzeugt das loslassen beispielsweise ein Kontextmenü. Dies jedoch will ich vermeiden. Dabei muss das Programm natürlich unterscheiden, wann es ein Kontextmenü zulassen soll (die Maus wurde zwischen Drücken und Loaslassen der Maustaste gar nicht oder kaum bewegt) und wann es genau dies verhindern soll (die Maus bewegt sich bei gedrückter Maustaste).
  • Bisherige Lösung:
    Ein globaler LowLevel-Mousehook der anhand den oben genannten Parametern entscheidet, ob er die Mausnachricht durch den Aufruf von CallNextHookEx weiterleiten oder durch Nichtaufruf die Nachrichten blockieren soll.

    Delphi-Quellcode:
    library mousehook;

    uses
      Windows,
      Messages;

    const
      WM_MOUSEHOOK = WM_USER + $0400;

    type
      TFileMapStuff = record
        aHandle: Cardinal;
        BlockRMB: boolean;
      end;

    const
      BLOCKINGCOUNT = 10;

    var
      HookHandle       : HHook;
      FileMapObj       : THandle;
      FileMapView      : ^TFileMapStuff;
      ComRec           : TFileMapStuff;
      MouseEventCounter : integer;
      MouseDown        : boolean;

    function MouseHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    var
      mhs: ^TMouseHookStruct;
    begin
      if (wParam <> WM_RBUTTONDOWN) and
         (wParam <> WM_RBUTTONUP) and
        Result := CallNextHookEx(HookHandle, Code, wParam, lParam);

      if code = HC_ACTION then
      begin
        FileMapObj := OpenFileMapping(FILE_MAP_READ, False,'HookMapFile');
        try
          if FileMapObj <> 0 then
          begin
            FileMapView := MapViewOfFile(FileMapObj, FILE_MAP_READ, 0, 0, 0);
            ComRec := FileMapView^;
            UnmapViewOfFile(FileMapView);
            CloseHandle(FileMapObj);
          end;
        except
          Result := CallNextHookEx(HookHandle, Code, wParam, lParam);
          exit;
        end;

        if ((wParam = WM_RBUTTONUP) or (wParam = WM_RBUTTONDOWN)) and not ComRec.BlockRMB then
        begin
          Result := CallNextHookEx(HookHandle, Code, wParam, lParam);
          exit;
        end;

        PostMessage(ComRec.aHandle, WM_MOUSEHOOK, wParam, lParam);

        if (wParam <> WM_RBUTTONDOWN) and
           (wParam <> WM_RBUTTONUP) and
           (wParam <> WM_MOUSEMOVE) then
          exit;

        if wParam = WM_RBUTTONDOWN then
        begin
          MouseDown := true;
          MouseEventCounter := 0;
        end
        else if wParam = WM_RBUTTONUP then
        begin
          MouseDown := false;

          if MouseEventCounter < BLOCKINGCOUNT then //Wurde die Maus nicht/kaum bewegt Tastenklick simulieren
          begin
            mhs := Pointer(lParam);
            MouseEventCounter := BLOCKINGCOUNT;
            mouse_event(MOUSEEVENTF_RIGHTDOWN, mhs^.pt.X, mhs^.pt.Y, 0, 0);
            mouse_event(MOUSEEVENTF_RIGHTUP, mhs^.pt.X, mhs^.pt.Y, 0, 0);
            Result := CallNextHookEx(HookHandle, Code, wParam, lParam);
            exit;
          end
        end;

        if (wParam = WM_MOUSEMOVE) and (MouseDown) then
          if MouseEventCounter < BLOCKINGCOUNT then
            Inc(MouseEventCounter);

      end;
    end;

    procedure InstallHook; stdcall;
    begin
      HookHandle := SetWindowsHookEx(14, @MouseHookProc, hInstance , 0); //14 ist der LL-MouseHook
      MouseEventCounter := 0;
      MouseDown := false;
    end;

    procedure UninstallHook; stdcall;
    begin
      UnhookWindowsHookEx(HookHandle);
    end;

    exports
    InstallHook,
    UninstallHook;

    begin
    end.
    Wie schon gesagt, ich kann mir nicht vorstellen, dass es so sauber ist, CallNextHookEx einfach nicht aufzurufen, oder?
  • Weiteres Problem:
    Mit diesem Lösungsansatz funktioniert zwar das Blockieren der Maustaste, jedoch tritt das im 1. Posting genannte Problem mit dem Highlighting auf. Aus diesem Grund möchte ich verhindern, dass ein Fenster die Nachrichten, die für das Highlighting verantwortlich sind, während des Zeichnens erhält.

greez

P.S.: Ich stelle gerade fest, dass für die Benutzung des MadCodeHooks anscheinend Adminprivilegien erforderlich sind. Liege ich da richtig? Wäre dies der Fall würde diese Möglichkeit für mich schon mal nicht in Frage kommen :|.

Mephistopheles 27. Mär 2005 22:39

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von c113plpbr
Du drehst mir die Worte im Mund um. So war das nicht gemeint.
Denn wenn du das Programm geschrieben hast, war es wohl nicht des Benutzers Schuld.

Aber wenn Madshi den nichtfunktionierenden Teil geschrieben hat, war es dennoch meine Schuld (s.o. dein Kommentar)?

Zitat:

Zitat von c113plpbr
Willst du damit sagen, dass alles was du programmierst, auf anhieb perfekt funktioniert? Irren ist nun mal Menschlich, und jeder macht Fehler. Aber Fehler kann man ausbessern, und so sollte man jedem die Chance geben, seine Fehler auszubessern, bevor man über ihn, oder sein Werk richtet.

Sollte man? Da bin ich nicht so sicher. In wievielen kommerziellen Projekten hast du schon mitgearbeitet?
Mit Worten läßt sich trefflich streiten,
Mit Worten ein System bereiten,
An Worte läßt sich trefflich glauben,
Von einem Wort läßt sich kein Iota rauben.


Zitat:

Zitat von c113plpbr
Ich will damit eigentlich nur sagen: auch ein Windows-Hook verbrät (mind.) soviel, wie ein API Hook. Daher sind API-Hook und Windows-Hook von der Performance her gleich einzustufen.

Nicht aber von Stabilität und Zuverlässigkeit. Kleiner Tip: Kernelmode-Programmierer behelfen sich seit langem mit SSDT-Patching. Es ist potentiell sehr gefährlich. Mit Windows XP und 2003 wurden einige neue Funktionen eingeführt, die statt Hooking einen Callback-Mechanismus einführen (nichts anderes also als Fensterhooks, nur ohne die Möglichkeit der "Interception"). Welchen Mechanismus bevorzugst du? Wie erklärst du einem Kunden, daß er einen nichtzertifizierten Treiber bekommt, obwohl ein zertifizierter unter Nutzung neuester Möglichkeiten möglich wäre?

Zitat:

Zitat von c113plpbr
Wie gesagt, ich habe nie behauptet, dass es die beste Methode ist. Aber es sollte ein Vorschlag sein. Ob man diesen nun "ernst" nimmt, oder nicht, überlasse ich jedem selbst.

Sieht nach einem Konsens aus.

Zitat:

Zitat von OrallY
Programmfunktion:
Der Benutzer soll im Endeffekt (genaue Funktion ist irrelevant) überall auf dem Bildschirm mit gedrückter rechter Maustaste zeichnen können. Die Anwendung selbst läuft im Hintergrund und soll den Dienst bereitstellen.

Sieht nach einem Job für SetCapture() aus.

Zitat:

Zitat von OrallY
Problem:
Drückt man irgendwo auf dem Bildschirm die Maustaste, erzeugt das loslassen beispielsweise ein Kontextmenü. Dies jedoch will ich vermeiden. Dabei muss das Programm natürlich unterscheiden, wann es ein Kontextmenü zulassen soll (die Maus wurde zwischen Drücken und Loaslassen der Maustaste gar nicht oder kaum bewegt) und wann es genau dies verhindern soll (die Maus bewegt sich bei gedrückter Maustaste).

Das mit dem Kontextmenü verstehe ich nicht, denn bei SetCapture() bekommt NUR dein Fenster Input.

Zitat:

Zitat von OrallY
Wie schon gesagt, ich kann mir nicht vorstellen, dass es so sauber ist, CallNextHookEx einfach nicht aufzurufen, oder?

Es ist prinzipiell schon "mal" okay, aber so generisch wie bei dir sieht ganz böse aus. Im Notfall hülfe nur noch Strg+Alt+Entf gegen deinen Hook, wenn der Amok läuft ;)

Zitat:

Zitat von OrallY
Weiteres Problem:
Mit diesem Lösungsansatz funktioniert zwar das Blockieren der Maustaste, jedoch tritt das im 1. Posting genannte Problem mit dem Highlighting auf. Aus diesem Grund möchte ich verhindern, dass ein Fenster die Nachrichten, die für das Highlighting verantwortlich sind, während des Zeichnens erhält.

Würde bei SetCapture() nicht auftreten. Lies dich mal schlau und implementiere deinen Ansatz. Bei weiteren Fragen postest du die einfach hier, bzw. postest hier einen Link zu einem neuen Thread (damit ich darauf aufmerksam werde).

Zitat:

Zitat von OrallY
P.S.: Ich stelle gerade fest, dass für die Benutzung des MadCodeHooks anscheinend Adminprivilegien erforderlich sind. Liege ich da richtig? Wäre dies der Fall würde diese Möglichkeit für mich schon mal nicht in Frage kommen :|.

Theoretisch sollten bei soetwas immer Debug-Privilegien reichen. Denn über Debug-Privilegien kannst du höchste Systemrechte erlangen.
Wenn es nur um das Hooken von Prozessen der gleichen Privilegienstufe (z.B. gleicher Benutzer) geht, sollte es aber möglich sein dies ohne spezielle Privilegien zu erreichen. Ich kenne seine aktuelle Implementierung nicht und habe keine Zeit mir das mit DeDe näher anzuschauen.

Es gab da mal eine OpenSource-Implementierung mit SetCapture(), die du eventuell als Anschauungsmaterial verwenden kannst. Zu finden war das (ist schon lange her) unter:
http://www.bendlins.de/nico/delphi/
Der Autor treibt sich meines Wissens auch hier im Forum herum, versuche ihn einfach zu kontaktieren. Ansonsten sind mir nur C/C++-Implementierungen bekannt.

Im Platform SDK gibt es ein Beispiel namens "Drawing Lines with the Mouse":
ms-help://MS.PSDK.1033/winui/winui/windowsuserinterface/userinput/mouseinput/usingmouseinput.htm
(Der Link gilt mit dem letzten aktuellen 2003er Platform SDK)

OrallY 28. Mär 2005 12:39

Re: Nachrichten vollkommen abfangen
 
Das Problem mit SetCapture ist, dass ich es ja erst setzen kann, wenn irgendwo die Nachricht WM_RBUTTONDOWN auftritt. Das hat wiederrum die Folge, dass ich genau diese Nachricht nicht mehr mit SetCapture "aufhalten" kann, da das MouseCapturing erst aktiv wird, nachdem WM_RBUTTONDOWN schon verschickt wurde. Der Effekt ist z.B. dass Fenster aktiviert werden oder der Cursor in einem Editor gesetzt.

Mephistopheles 28. Mär 2005 12:51

Re: Nachrichten vollkommen abfangen
 
Hast du schonmal versucht das SetCapture() aufzurufen, ohne ein sichtbares Fenster haben zu müssen? Das einzige Problem sollte doch sein, daß du irgendein spezielles Signal geben mußt, damit dein Fenster bescheid bekommt, daß es SetCapture() aufrufen muß. Ich hab's zugegebenermaßen so noch nicht getestet - da bisher immer ein Ausgangspunkt (/-fenster) für SetCapture() sichtbar existierte.

OrallY 28. Mär 2005 13:00

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von Mephistopheles
Das einzige Problem sollte doch sein, daß du irgendein spezielles Signal geben mußt, damit dein Fenster bescheid bekommt, daß es SetCapture() aufrufen muß.

Welches Signal jedoch und wann soll es ausgelöst werden? Der Auslöser zum MouseCapturing ist ja eine Mausnachricht ("Maustaste unten"), die ich mit einem Hook auffange. Jedoch schlüpft dann die Auslöser-Nachricht durch das Netz und erreicht eine Anwendung.

Meine Anwendung soll ja im Hintergrund laufen und erst aktiv werden, wenn der Benutzer z.b. die rechte Maustaste drückt um zu zeichnen.

Mephistopheles 28. Mär 2005 13:23

Re: Nachrichten vollkommen abfangen
 
Rechtsklick reicht meines Erachtens nach nicht aus. Es ist zu unspezifisch und gemeinhin das Signal ein Kontextmenü zu zeigen. Es müßte z.B. zur gleichen Zeit auch eine Taste gedrückt sein.

OrallY 28. Mär 2005 13:27

Re: Nachrichten vollkommen abfangen
 
Genau dies möchte ich aber nicht :wink:. Die Maus muss ausreichen.

In einem Posting zuvor erwähntest du, dass es möglich ist mittels Subclassing und DLL-Injection die Nachrichtenweitergabe an Anwendungen zu verhindern.
Könntest du das bitte genauer Erläutern?

Mephistopheles 28. Mär 2005 13:44

Re: Nachrichten vollkommen abfangen
 
Subclassing ist nichts anderes, als daß du für (jeweils) ein bestimmtes Fenster die Fensterfunktion durch eine eigene austauscht und so wahlweise vor der Bearbeitung durch die alte Fensterfunktion oder danach deine Bearbeitung vornimmst. Alternativ kannst du natürlich auch einfach die orginale Fensterfunktion nicht mehr aufrufen, wodurch die Mausnachrichten z.B. abgefangen werden können.

Das Gegenteil davon ist Superclassing, wo die Fensterfunktion einer kompletten Fensterklasse ausgetauscht wird.

Für DLL-Injection gibt es dutzende Methoden. Die leichteste ist auf NT-basierten Systemen in einem ganz bestimmten Schlüssel den Namen deiner DLL abzulegen. Damit wird deine DLL in jeden gestarteten Prozess geladen.

OrallY 28. Mär 2005 17:16

Re: Nachrichten vollkommen abfangen
 
Nach einigem rumstöbern im Inet und im PSDK bin ich wieder auf den GetMsg-Hook gestoßen. Und was sehen meine entzückten Äuglein in er Beschreibung? "...or modify the message...". Bingo!

Tritt irgendwo eine WM_RBUTTONDOWN-Nachricht auf, setzt der Hook sie auf WM_NULL. Funktioniert fast alles wunderbar, bis auf eine ziemlich nervende Tatsache:

Drückt man irgendwo die rechte Maustaste wird das darunterliegende Fenster trotz Hook aktiviert. Die Nachrichten werden erfolgreich geblockt. Jedoch erhält das Fenster, wenn es nicht aktiv ist und mit rechts ein Klick darauf erfolgt die Nachricht (dezimal) 45056 und beim Verlust des Fokuses 45057.
Diese Nachrichten scheinen nicht durch den Hook zu gehen und können daher auch nicht blockiert werden. Ich denke aber, dass sie irgendwas damit zu tun haben.

Interessanterweise zeigt ein Fenster keine Reaktion, wenn ich eine solche Nachricht schicke. :?

Was sind das für Nachrichten? $B000=45056 ist niergends aufgelistet :gruebel:.

greez

Edit: Habe gerade eine Fund gemacht: http://groups.google.de/groups?hl=de...enetserver.com

45056 scheint eine VCL-Interne Nachricht zu sein (CM_ACTIVATE). Dann hat das wohl nichts mit dem Problem zu tun :|.

Mephistopheles 28. Mär 2005 19:39

Re: Nachrichten vollkommen abfangen
 
Es könnte einerseits schon mit dem Problem zu tun haben, andererseits wäre das aber nur auf VCL-Programme anwendbar. Bei anderen dürfte das Problem ja dann nicht auftauchen, oder?

OrallY 29. Mär 2005 22:32

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von Mephistopheles
Es könnte einerseits schon mit dem Problem zu tun haben, andererseits wäre das aber nur auf VCL-Programme anwendbar. Bei anderen dürfte das Problem ja dann nicht auftauchen, oder?

Doch, dieses Problem tritt leider bei allen Anwendungen auf. Dem Anschein nach, ist es einfach nur eine VCL-interne Control-Message die irgendwas in den unendlichen Weiten der VCL bewirkt.

Vermutlich wertet das OS die Mausnachrichten noch vor meinem GetMsg-Hook aus und setzt dann gegebenenfalls Fenster aktiv, bevor dies mein Hook hätte verhindern können :|. Ein LowLevel-MH scheint vor dieser Auswertung zu sitzen :gruebel:. Dort jedoch habe ich keinerlei Möglichkeiten die Nachrichten zu manipulieren, außer die Hook-Chain zu unterbrechen.

Momentan bin ich mit meinem Latein ziemlich am Ende. Es muss jedoch irgendwie funktionieren, da ich ein Programm kenne, das genau dies macht. Die Entwickler scheinen allerdings nicht besonders Kommunikativ zu sein, wenn es um ihren Source geht...

Bin für alle Idee nach wie vor offen :wink:.

greez

Mephistopheles 30. Mär 2005 07:43

Re: Nachrichten vollkommen abfangen
 
Zitat:

Zitat von OrallY
Momentan bin ich mit meinem Latein ziemlich am Ende. Es muss jedoch irgendwie funktionieren, da ich ein Programm kenne, das genau dies macht. Die Entwickler scheinen allerdings nicht besonders Kommunikativ zu sein, wenn es um ihren Source geht...

Bin für alle Idee nach wie vor offen :wink:.

Ich habe aktuell keine Ideen mehr.

OrallY 30. Mär 2005 21:53

Re: Nachrichten vollkommen abfangen
 
Der o.g. Entwickler hat sich nun doch noch gemeldet.
Er hat das Problem ebenfalls mit Unterbrechen der HookChain gelöst (Ist bei näherer Betrachtung eigentlich das Naheliegendste, da dies ja eigentlich genau die Absicht ist, die das Programm verfolgt: Das Durchstellen von Mausnachrichten verhindern.). Allerdings habe ich festgestellt, dass ein LL-Mousehook doch nicht notwendig ist, um die Hook-Chain zu unterbrechen! Ein einfacher Mousehook reicht durchaus :wall: :mrgreen:. Und dank dem Tipp von Mephistopheles (SetCapture) ist nun auch das Highlighting kein Problem mehr.

Vielen Dank an alle die mir geholfen haben!


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