Announcement

Collapse
No announcement yet.

wie programmiert man eine HOOK-Funktion?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • wie programmiert man eine HOOK-Funktion?

    guten tag

    wenn ich so programme schreibe wie eine lupe oder eine Tastaturmaus
    für linkshänder benötigt man wohl eine hookfunktion, weil das Programm
    nachher in ganz windows funktionieren soll und auch wenn eine andere
    Anwendung aktiv ist. oder gibt es da noch andere alternativen???

    auf jeden fall wäre es ein feiner zug, wenn mir jemand erklären könnte,
    wie man eine hook-funktion programmiert!!!!

    mfg

    markus lemcke
    Herzliche Grüße

    Markus Lemcke
    barrierefreies Webdesign

  • #2
    <pre>
    unit hookfrm;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Buttons, ComCtrls;

    type
    TFormMain = class(TForm)
    BitBtnClose: TBitBtn;
    Label1: TLabel;
    Bevel2: TBevel;
    Bevel3: TBevel;
    Label2: TLabel;
    Label3: TLabel;
    LabelX: TLabel;
    LabelY: TLabel;
    StatusBar1: TStatusBar;
    RBSetCapture: TRadioButton;
    RBReleaseCapture: TRadioButton;
    RadioButton1: TRadioButton;
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
    Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure RBSetCaptureClick(Sender: TObject);
    procedure RBReleaseCaptureClick(Sender: TObject);
    private
    { Private-Deklarationen }
    public
    { Public-Deklarationen }
    end;

    var
    FormMain : TFormMain;
    hHookHandle : hHook; // Handle auf den Hook

    // Hookfunktion für SetWindowsHookEx
    function HookProc(iCode : Integer;
    wParam : WPARAM;
    lParam : LPARAM): LongInt; stdcall;

    implementation

    {$R *.DFM}

    (* Anzeige der Mauskoordinaten relativ bezogen auf das eigene
    Formular. Zusätzlich wird der Fenstertiteltext sowie der
    Fensterklassennamen von dem Fenster angezeigt, das sich
    gerade unter der Maus befindet. *)

    procedure TFormMain.FormMouseMove(Sender: TObject;
    Shift: TShiftState;
    X, Y: Integer);
    const
    iBufferSize = 30;
    var
    aPt : TPoint;
    aWnd : hWnd;
    sClass : array[0..iBufferSize] of Char;
    sText : array[0..iBufferSize] of Char;
    begin
    // Relative Position zum Formular
    LabelX.Caption := IntToStr(X);
    LabelY.Caption := IntToStr(Y);
    // Position zum Desktop-Fenster von Window
    GetCursorPos(aPt);
    // Fensterhandle unter der Maus ermitteln
    aWnd := WindowFromPoint(aPt);
    // Fensterklassenname auslesen
    GetClassName(aWnd, sClass, iBufferSize);
    // Fensterbeschriftung auslesen
    GetWindowText(aWnd, sText, iBufferSize);
    if sText = '' then sText := '[kein Titel]';
    StatusBar1.SimpleText := sText + ' : ' + sClass
    end;

    (* Die leere Hook-Funktion macht überhaupt nichts, sondern
    ruft sofort die nächste auf. Um das "alte" SetCapture-
    Verhalten von Windows 3.x auch in Windows 95 wiederher-
    zustellen, muß nur eine Hook-Funktion installiert werden.
    Windows 95 schaltet dann automatisch von der asynchronen
    Betriebsart auf die Vorgängerversion zurück. *)

    function HookProc(iCode : Integer;
    wParam : WPARAM;
    lParam : LPARAM): LongInt; stdcall;
    begin
    Result := CallNextHookEx(hHookHandle, iCode, wParam, lParam)
    end;

    (* Formular wird erzeugt -> Hookfunktion installieren *)

    procedure TFormMain.FormCreate(Sender: TObject);
    begin
    // Hook setzen
    hHookHandle := SetWindowsHookEx(WH_JournalRecord, HookProc,
    hInstance, 0);
    end;

    (* Formular wird zerstört -> Hookfunktion entfernen *)

    procedure TFormMain.FormDestroy(Sender: TObject);
    begin
    // Hook entfernen
    if hHookHandle <> 0 then begin
    UnHookWindowsHookEx(hHookHandle);
    hHookHandle := 0;
    end
    end;

    (* Radiobutton schaltet den Mausfang ein und sperrt den
    Schließen-Button. *)

    procedure TFormMain.RBSetCaptureClick(Sender: TObject);
    begin
    SetCapture(Handle);
    BitBtnClose.Enabled := False;
    end;

    (* Radiobutton schaltet den Mausfang aus und gibt den
    Schließen-Button wieder frei. *)

    procedure TFormMain.RBReleaseCaptureClick(Sender: TObject);
    begin
    ReleaseCapture;
    BitBtnClose.Enabled := True;
    end;

    initialization
    hHookHandle := 0;

    end.
    </pre&gt

    Comment


    • #3
      guten tag herr kosch,

      folgende zeilen in ihrem code ermitteln das fensterhandle:

      // Fensterhandle unter der Maus ermitteln
      aWnd := WindowFromPoint(aPt);

      was ist wenn ich innerhalb des fensters ein menü oder einen button anklicken möchte???

      mfg

      marku
      Herzliche Grüße

      Markus Lemcke
      barrierefreies Webdesign

      Comment


      • #4
        Hallo Markus,

        in diesem Fall kümmert sich Windows darum. Ein Mausklick wird immer in der Botschaftswarteschlange des Threads abgelegt, dem das darunterliegende Fenster gehört (solange kein Capture aktiv ist). Der Hook ist so etwas wie ein T-Stück, der die Information "abzweigt", ohne das originale Ereignis zu verfälschen. Im Beispiel rufe ich sofort den nächsten Hook auf, und reiche somit das Ereignis nur weiter.

        Im o.g. Beispielprojekt wird das eigene Programm ständig informiert, wenn sich der Mauszeiger bewegt hat. Der Aufruf von <b>WindowFromPoint</b> soll nur demonstrieren, das das eigene Programm jederzeit das Fenster ermitteln kann, über dem sich der Mauszeiger gerade befindet. Trotzdem kann dieses "fremde" Fenster vom Anwender ganz normal bedient werden - da der Hook für die fremde Anwendung "unsichtbar" ist

        Comment


        • #5
          Hallo,

          Ich habe ein Problem und eine Frage zu den Hooks.
          Zuerst die Frage:
          Warum ist der obengenannte Hook nicht
          nicht einer Dll untergebracht, wenn er doch Systemweit ist.
          Laut API-Hilfe ist dies ein Muss und ich habe selbst GFP's
          erzeugt wenn ich dies nicht tat.
          Nun mein Problem:
          Ich habe eine Dll mit einem systemweiten Hook fuer
          wh_CallWindowProc erzeugt.
          Die zu hookenden Msg wollte ich ueber eine CallbackProc an ein
          anderes Delphifenster uebergeben.
          Die Dll mit StartHook / StopHook funktioniert einwandfrei und auch
          die HookProc wird erreicht. Aber meine Callback nicht.
          Dem ging ich auf die Spur mit Logging in ein File von der DLL aus.

          Daraus lies sich eindeutig feststellen, dass nach dem SetWindowsHookEx
          ein Abbild der DLL fuer jede laufende APP erzeugt wurde
          (in deren Prozessmemory). Da es nun so ist, dass alle Abbilder
          der DLL's ihre eigenen Datenbereiche bekommen war in den Abbildern
          die DLL-Variable CallBack nicht mehr auf meine urspruenglich gesetzte
          CallBackProc initialisiert.
          Wie kann man dann aber eine CallBackProc nutzen?
          Das Logging umfasste das Laden der DLL (begin end. Abschnitt),
          das Setzen der CallBackProc und Starten / Stoppen des Hooks.
          Dabei liess ich mir auch die Adressen und Inhalte der Variablen
          CallBackProc und HookID mitschreiben. Somit sah man eindeutig
          das mehrfache laden und auch das die Var je auf verschiedenen
          Adressen lagen und auch nur in der 1.Instance der DLL korrekt
          init. waren.

          Vielen Dank
          C

          Comment


          • #6
            Hallo,

            auch im Win32-API gibt es kaum Regeln ohne Ausnahmen ;-) <br>
            Generell muss eine globale (systemweite) Hook-Funktion in einer DLL implementiert werden. Allerdings gibt es Ausnahmen - und eine dieser Ausnahmen habe ich in meine o.g. Beispielprojekt für <b>Windows 95</b> vorgestellt. Es gibt einen Grund, warum in diesem Beispiel die folgende Kommentarzeile enthalten ist:
            <i>Die leere Hook-Funktion macht überhaupt nichts, sondern
            ruft sofort die nächste auf. Um das "alte" SetCapture-
            Verhalten von Windows 3.x auch in Windows 95 wiederher-
            zustellen, muß nur eine Hook-Funktion installiert werden.
            Windows 95 schaltet dann automatisch von der asynchronen
            Betriebsart auf die Vorgängerversion zurück. </i>

            Unter <b>Windows 9x</b> gibt es den Sonderfall des Kompatibilitätsmodus</b> - beim Aktivieren des Hook schaltet Windows 9x in den von Win16 (Windows 3.x) gewohnten Modus um. Unter Windows 3.x gab es nur einen Prozessraum - so dass alle Module im gleichen Speicherbereich ausgeführt werden konnten. Daher muss in diesem konkreten Fall auch unter Windows 9x die Hook-Funktion nicht in einer DLL sein, da sich Windows 9x in der Simulation darum kümmert.

            Dieser Kompatibilitätsmodus sollte jedoch nur die Ausnahme sein, zumal er unter Windows NT nicht zur Verfügung steht. Also wird die Hook-DLL benötigt, die in der Tat von Win32 in jeden betroffenen Adressraum geladen wird und sich dabei frisch initialisiert. Um die eigenen (gemeinsam genutzten) Daten zu setzen/auszulesen, muss die DLL und die Anwendung über ein <b>Memory-Mapped-File</b> (MMF) zusammenarbeiten. Borland hat dazu ein sehr umfangreich kommentiertes Beispiel als TI (Technical Information) auf seinen Web-Seiten veröffentlicht

            Comment


            • #7
              Vielen Dank das war sehr hilfreich.

              C

              Comment


              • #8
                guten tag herr kosch,

                habe kurz einen test gemacht.
                auf dem formular war eine filelistbox.

                procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
                var
                apt:tpoint;
                awnd:hwnd;
                begin
                if key = '1' then
                begin
                // Position zum Desktop-Fenster von Window
                GetCursorPos(aPt);
                // Fensterhandle unter der Maus ermitteln
                aWnd := WindowFromPoint(aPt);
                sendmessage(awnd,wm_lbuttondown,apt.x,apt.y);

                end;

                klappt aber nicht warum???????

                mfg

                marku
                Herzliche Grüße

                Markus Lemcke
                barrierefreies Webdesign

                Comment

                Working...
                X