Delphi-PRAXiS
Seite 2 von 6     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Maus sperren während Tastatureingabe (https://www.delphipraxis.net/124241-maus-sperren-waehrend-tastatureingabe.html)

blackdrake 17. Nov 2008 21:16

Re: Maus sperren während Tastatureingabe
 
Meinst du, es sollte so aussehen?

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  h: hwnd;
begin
  h := WindowHandle;
  InstallHooks(h); // EXCEPTION
  WM_MOUSEHOOKMSG:=getprop(h,mousmsg);
  WM_KEYBHOOKMSG:=getprop(h,keybmsg);
end;
Wirft aber auch eine AV ab.

Das Problem ist, dass ich vom DP-Tutorial keine Belegung des hWnd's sehen konnte.

Dort wird nämlich die API-Funktion mittels
Delphi-Quellcode:
DialogBoxParam(HInstance, MAKEINTRESOURCE(DIALOG1), 0, @dlgfunc, 0);
aufgerufen, jedoch kann ich dann nicht wirklich die dlgfunc-Parameter, die auch die hWnd enthält, sehen...

In sofern weiß ich nicht genau, welches Handle überhaupt verlangt ist...

Sir Rufo 17. Nov 2008 21:18

Re: Maus sperren während Tastatureingabe
 
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  h: hwnd;
begin
  h := Form1.Handle; // <--- Eher so ...
  InstallHooks(h); // EXCEPTION
  WM_MOUSEHOOKMSG:=getprop(h,mousmsg);
  WM_KEYBHOOKMSG:=getprop(h,keybmsg);
end;

blackdrake 17. Nov 2008 21:22

Re: Maus sperren während Tastatureingabe
 
Hallo.

Funktioniert leider immer noch nicht.

Ich denke, die AV kommt aufgrund einer ungültigen DLL-Interaktion. Wäre nur das Handle falsch, würde das wahrscheinlich nicht zu einer AV führen.

Hast du eine Idee?

Gruß
blackdrake

blackdrake 17. Nov 2008 23:56

Re: Maus sperren während Tastatureingabe
 
Hallo,

Der Fehler lag beim GetProcAddress, da bei den 2 Tutorials einmal von *Hook und einmal von *Hooks die Rede war.

Ich habe jetzt einen fast funktionierenden Code, jedoch gibt es noch 2 Dinge, mit denen ich Probleme habe:

1. Die Strg-Taste wird auch als Taste angesehen ... hier muss sich dringend noch eine Allgemeine Lösung finden, weil Strg+Maustaste ja legitim sind
2. Das Sperren der Maustaste funktioniert nicht. Eigentlich dachte ich, es genüge, einfach das WndProc, das man verwerfen möchte, einfach nicht mehr per inherited weiterzureichen, doch es funktioniert einfach nicht.

Zum Testen: Ich habe während die Anwendung im Hintergrund läuft in einem Notepad etwas eingetippt. Das Fenster im Hintergrund zeigt als Debugausgabe "Gesperrt". Während der Eingabe klicke ich in meinen geschriebenen Text hinein. Nach der Eingabe werden die Textstellen markiert, weil scheinbar die Mausereignisse doch noch im Eingabepuffer waren und nicht durch die Hook-DLL verworfen wurden.

Code (DLL hooks.dll in den oberen Posts):

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    debug_tmr: TTimer;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure debug_tmrTimer(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  public
    last_keyboard_input: DWORD;
    procedure WndProc(var Message:TMessage); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TInstallHook = function(Hwnd: THandle): Boolean; stdcall;
  TUninstallHook = function: Boolean; stdcall;

var
  InstallHooks: TInstallHook;
  UninstallHooks: TUninstallHook;
  lib: Cardinal;
  WM_MOUSEHOOKMSG: Cardinal = 0;
  WM_KEYBHOOKMSG: Cardinal = 0;

const
  mousmsg='MouseHookMessage_Assarbad';
  keybmsg='KeyboardHookMessage_Assarbad';

const
  sperrdauer = 3000; // 3 Sekunden, später Variabel

// ToDo: Programm total lahm, wenn Delphi gestartet ist
// (auch außerhalb des Debuggers) ?
procedure TForm1.WndProc(var Message:TMessage);
var
  difference: DWORD;
begin
  if Message.Msg = WM_KEYBHOOKMSG then
  begin
    inherited WndProc(Message);

    // Eine Taste wurde gedrückt, wir merken uns den Zeitpunkt
    last_keyboard_input := GetTickCount();

    // ToDo: Tasten wie Strg dürfen nicht mitgezählt werden,
    // da diese in Kombination mit der Maustaste OK sind!
  end
  else if Message.Msg = WM_MOUSEHOOKMSG then
  begin
    difference := GetTickCount() - last_keyboard_input;

    if (difference <= sperrdauer) and
       ((Message.wParam = WM_LBUTTONDBLCLK) or
        (Message.wParam = WM_LBUTTONDOWN) or
        (Message.wParam = WM_LBUTTONUP)) then
    begin
      // Ereignis verwerfen, da linke Maustaste innerhalb
      // der Sperrzeit gedrückt wurde

      // Something ToDo ?

      // Debug: Zeigen, dass etwas gesperrt wurde
      label2.Caption := 'Sperrung: ' + IntToStr(GetTickCount());
    end
    else
    begin
      // Sonstiges Mausereignis bzw. Mausklick außerhalb
      // der Sperrzeit erlauben
      inherited WndProc(Message);
    end;
  end
  else
  begin
    // Andere Ereignisse durchlassen
    inherited WndProc(Message);
  end;
end;

procedure TForm1.debug_tmrTimer(Sender: TObject);
var
  difference: DWORD;
begin
  difference := GetTickCount() - last_keyboard_input;

  if difference > sperrdauer then
  begin
    label1.Caption := 'Freigegeben';
  end
  else
  begin
    label1.Caption := 'Gesperrt';
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  UnInstallHooks;
  WM_MOUSEHOOKMSG:=0;
  WM_KEYBHOOKMSG:=0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  lib := LoadLibrary('hooks.dll');
  if lib <> INVALID_HANDLE_VALUE then
  begin
    InstallHooks := GetProcAddress(lib, 'InstallHooks');
    UnInstallHooks := GetProcAddress(lib, 'UninstallHooks');
  end
  else
  begin
    ShowMessage('Hook could not be initialized. Please check "hooks.dll".');
    Application.Terminate;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeLibrary(lib);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  InstallHooks(Handle);
  WM_MOUSEHOOKMSG:=getprop(Handle, mousmsg);
  WM_KEYBHOOKMSG:=getprop(Handle, keybmsg);
end;

end.
Gruß
blackdrake

Sir Rufo 18. Nov 2008 00:27

Re: Maus sperren während Tastatureingabe
 
Zitat:

Zitat von blackdrake
Hallo,

Der Fehler lag beim GetProcAddress, da bei den 2 Tutorials einmal von *Hook und einmal von *Hooks die Rede war.

Ich habe jetzt einen fast funktionierenden Code, jedoch gibt es noch 2 Dinge, mit denen ich Probleme habe:

Das sieht doch schon gut aus

Zitat:

Zitat von blackdrake
1. Die Strg-Taste wird auch als Taste angesehen ... hier muss sich dringend noch eine Allgemeine Lösung finden, weil Strg+Maustaste ja legitim sind

Ich würde die STRG-Taste einfach aus der Betrachtung lassen:
a) ist sie sehr weit weg vom Mousepad
b) wird diese beim Schreiben von Text eher selten benötigt
c) wird beim Schreiben von Text innerhalb der Sperrzeit eine weitere Taste gedrückt. Nur mit der STRG-Taste ist es schwierig einen Text zu verfassen :mrgreen:

Zitat:

Zitat von blackdrake
2. Das Sperren der Maustaste funktioniert nicht. Eigentlich dachte ich, es genüge, einfach das WndProc, das man verwerfen möchte, einfach nicht mehr per inherited weiterzureichen, doch es funktioniert einfach nicht.

Da es sich um eine Message handelt, geht die bei Winows auch in und durch eine Warteschlange. Also muss man auch aktiv werden, wenn diese Message aus der Warteschlange raus soll.
Aber das weiß ich adhoc auch nicht ... vielleicht habe ich nachher, wenn der planet wieder scheint, etwas zeit, mir das mal anzusehen ;-)

Zitat:

Zitat von blackdrake
Zum Testen: Ich habe während die Anwendung im Hintergrund läuft in einem Notepad etwas eingetippt. Das Fenster im Hintergrund zeigt als Debugausgabe "Gesperrt". Während der Eingabe klicke ich in meinen geschriebenen Text hinein. Nach der Eingabe werden die Textstellen markiert, weil scheinbar die Mausereignisse doch noch im Eingabepuffer waren und nicht durch die Hook-DLL verworfen wurden.

jo ...

cu

Oliver

blackdrake 18. Nov 2008 17:35

Re: Maus sperren während Tastatureingabe
 
Hallo.

Ich weiß nicht, wie ich hier die Maus-Aktion rückgängig machen soll.

Delphi-Quellcode:
function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
//es ist ebenfalls moeglich die Bearbeitung an eine Bedingung zu knuepfen
//it's possible to call CallNextHookEx conditional only.
  Result := CallNextHookEx(Mouse_HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit; //wenn code kleiner 0 wird nix gemacht
                //if code smaller 0 nothing has to be done
    FALSE:
      begin
//Hier kann jetzt alles bearbeitet werden
//Here one can work with the parameters
        setprop(WindowHandle, 'mous_ncode', nCode);
        setprop(WindowHandle, 'mous_hwnd', PMOUSEHOOKSTRUCT(lParam)^.hwnd);
        setprop(WindowHandle, 'mous_hitt', PMOUSEHOOKSTRUCT(lParam)^.wHitTestCode);
        setprop(WindowHandle, 'mous_xpos', PMOUSEHOOKSTRUCT(lParam)^.pt.x);
        setprop(WindowHandle, 'mous_ypos', PMOUSEHOOKSTRUCT(lParam)^.pt.y);
        SendMessage(HWND_BROADCAST, WM_MOUSEHOOKMSG, wParam, lParam);
      end;
  end;
end;
Dieses Konstrukt der DLL sieht nicht aus wie eine WndProc-Schleife, bei der man eine nicht gebrauchte Message einfach nicht per inherited weiterreicht...

Ich glaube, dass ich nach SendMessage() das result neutralisieren muss, wenn ich das Ereignis verwerfen möchte.

Das Problem: Die Message WM_MOUSEHOOKMSG müsste dann ja auch noch ein Ergebnis zurückliefern, in dem steht, ob das WM_MOUSE* Ereignis gelöscht wird oder nicht.

Gibt es denn keine bessere Lösung, bei der ich das Maus-Links-Klick-Ereignis löschen kann, ohne die DLL unnötig zu erweitern?

Gruß
blackdrake

SirThornberry 18. Nov 2008 17:53

Re: Maus sperren während Tastatureingabe
 
Vielleicht ist der Maushook dann der falsche Ansatz?! Es gibt auch Messagehooks :-)

blackdrake 18. Nov 2008 18:20

Re: Maus sperren während Tastatureingabe
 
Och nö, wie soll denn das jetzt gehen?

Ich habe mal versucht, http://delphigeek.blogspot.com/2007/...in-delphi.html auf Left-Button zu übertragen, jedoch bekomme ich bei der Implementierung nur einen Programmfehler.

Außerdem wird nirgends beschrieben, WIE dieser Left-Mouse-Hook (im Link Middle-Mouse-Hook) nun angewandt wird, also dass der Hook sich tatsächlich als Ereignis auf meine Anwendung auswirkt.

Folgendes scheint nicht zu funktionieren:

Delphi-Quellcode:
public
  procedure Test(var msg: TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
end;

procedure RunHook; stdcall; external 'left_mouse_hook.dll' name 'RunHook';
procedure KillHook; stdcall; external 'left_mouse_hook.dll' name 'KillHook';

procedure TForm1.Test(var msg: TWMNCLButtonDown);
begin
  Button1.Caption := IntToStr(GetTickCount());
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  RunHook;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  KillHook;
end;
Kann mir bitte jemand helfen? Ich möchte ein systemglobales Maus-Hook mit der möglichkeit, das Mausereignis innerhalb meiner Anwendung (also nicht in der DLL) rückgängig zu machen.

Apollonius 18. Nov 2008 18:36

Re: Maus sperren während Tastatureingabe
 
Erstelle eine MMF mit einem eindeutigen Namen (am besten ein GUID). In diese schreibst du von der Anwendung aus das Fensterhandle deines Forms. In der DLL öffnest du die MMF und schickst deine eigene Nachricht an das Fenster, am besten eine mit RegisterWindowMessage registrierte. Dieses Senden sollte unbedingt mit SendMessageTimeout erfolgen und mit den Flags SMTO_ABORTIFHUNG sowie SMTO_BLOCK! Alles andere kann dazu führen, dass das System nicht mehr zu gebrauchen ist. Dein Formular kann mit dem Nachrichten-Ergebnis mitteilen, ob der Hook die alte Nachricht weiterleiten oder verändern soll.

blackdrake 18. Nov 2008 18:39

Re: Maus sperren während Tastatureingabe
 
Oh je, sowas kompliziertes habe ich noch nicht gehört :pale: Geht denn das nicht auch einfacher oder irgendwie als existierenden Code, den man umändern kann?


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:19 Uhr.
Seite 2 von 6     12 34     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz