Delphi-PRAXiS
Seite 1 von 2  1 2      

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 12:53


Maus sperren während Tastatureingabe
 
Hallo.

Ich habe bei meinem Notebook folgendes Problem: Ich lege meine Handflächen während des Tippens meistens auf die Mitte der Tastatur, was bewirkt, dass ich mit den Handballen ständig auf das (meiner Meinung etwas zu große) Touchpad komme und ich somit während des Tippens ständig in das Textfeld klicke und mein Text dadurch ziemlich verunstaltet wird.

Nach einer Recherche habe ich herausgefunden, dass viele Leute dieses Problem haben und dass es bis jetzt kein Tool dafür gibt. Die einzigste Workaround-Lösung ist, den Mauszeiger auf ein neutrales Element des Forms (im Browser z.B. die Lesezeichenleiste) zu setzen, bei der ein Klick keine Aktion und keinen Fokusverlust des Eingabefeldes bewirken kann. Das ist aber meiner Meinung nach unzureichend.

Deswegen wollte ich mal versuchen, ein Tool zu entwickeln, dass die Maus während einer Tastatureingabe sperrt (Touchpad separat sperren ist ja unter Windows-Ebene nicht wirklich allgemein machbar)

Ich stelle mir das so vor:
1. Das Ereignis einer Tastatureingabe wird auf Betriebssystemebene erfasst - im Notfall müsste man mit den Hook-DLLs von Keyloggern arbeiten, jedoch dann schlagen AntiViren-Programme zu, da sie ein Keylogger-Malware vermuten
2. Während der nächsten x-Sekunden wird die Maus in Sachen Bewegungen und Klicks gesperrt. (Eventuell könnte man noch einstellen, dass nur Klicks und Bewegungen nicht gesperrt werden)

Wie kann ich das realisieren?

- Man kann die letzte Eingabe mittels GetLastInputInfo() prüfen, jedoch wird dort auf Tastatur und Maus überprüft. Ich will jedoch nur den Zeitpunkt des letzten Tastenanschlags
- Und wie man die Maus komplett oder nur partiell sperrt, weiß ich auch nicht. Man müsste eventuell eine Windows-Message abfangen und diese nach dem Erhalt als ungültig erklären, oder?

Gruß
blackdrake

SirThornberry 17. Nov 2008 13:02

Re: Maus sperren während Tastatureingabe
 
viele Notebooks bieten die möglichkeit mit einer seperaten Taste oder in Verbindung mit FN das Touchpad zu deaktivieren. Falls diese Möglichkeit nicht vorhanden ist und man mit dem Touchpad nicht klar kommt ist eine weitere Möglichkeit das Touchpad im Gerätemanger zu deaktivieren und eine externe Maus anzuschließen.

blackdrake 17. Nov 2008 13:06

Re: Maus sperren während Tastatureingabe
 
Hallo.

Ich möchte es wirklich gerne per Tool bewältigen.

Mein Notebook besitzt eine [Fn]-Tastenkombination zur Deaktivierung des Touch-Felds. Das könnte ich machen, wenn ich sehr lange Texte tippe, aber für normale Benutzung wäre es nicht günstig, das Touch-Feld andauernd zu aktivieren und zu deaktivieren. Denn ich möchte das Touchfeld ja zwischen den Eingaben wirklich benutzen. Eine externe Maus ist auch nicht überall passend, besonders wenn es an Platz fehlt, man im Zug sitzt etc. Eine komplette deaktivierung des Touchfields wäre mir also nicht ganz so recht.

Gruß
blackdrake

blackdrake 17. Nov 2008 13:51

Re: Maus sperren während Tastatureingabe
 
Hallo.

In einem kleinen Testprogramm habe ich schon einen kleinen Fortschritt erwirkt.

Wenn ein Button "Maus 3 Sekunden sperren" geklickt wird, wird die Maus innerhalb des Forms für 3 Sekunden gesperrt.

Folgendes fehlt jetzt noch:
1. Der Hook muss die Maus Systemweit sperren
2. Ich muss noch herausfinden, wann die Tastatur zuletzt bedient wurde (aber NUR die Tastatur)

Delphi-Quellcode:
var
  HookID: THandle;

function MouseProc(nCode: Integer; wParam, lParam: Longint): Longint; stdcall;
var
  szClassName: array[0..255] of Char;
begin
  case nCode < 0 of
    True:
      Result := CallNextHookEx(HookID, nCode, wParam, lParam)
      else
        case wParam of
          // Linke Maustaste sperren
          WM_LBUTTONDOWN,
          WM_LBUTTONUP,
          WM_LBUTTONDBLCLK:
            begin
              GetClassName(PMOUSEHOOKSTRUCT(lParam)^.HWND, szClassName, SizeOf(szClassName));
              Result := HC_SKIP
            end
            else
              Result := CallNextHookEx(HookID, nCode, wParam, lParam);
        end;
  end;
end;

procedure DestroyHook;
begin
  if HookID <> 0 then
  begin
    UnHookWindowsHookEx(HookID);
  end;
end;

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

procedure TForm1.sperre_maus_fuer_3_sekundenClick(Sender: TObject);
begin
  // TODO: SYSTEM-GLOBAL DEN HOOK FÜR WM_MOUSE SETZEN!
  HookID := SetWindowsHookEx(WH_MOUSE, MouseProc, 0, GetCurrentThreadId());
  timer1.enabled := true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  DestroyHook;
end;
Gruß
blackdrake

Luckie 17. Nov 2008 13:59

Re: Maus sperren während Tastatureingabe
 
Zitat:

Zitat von blackdrake
1. Der Hook muss die Maus Systemweit sperren

Der Cod emus sin einer DLL liegen.
Zitat:

2. Ich muss noch herausfinden, wann die Tastatur zuletzt bedient wurde (aber NUR die Tastatur)
Schreib noch einen Tastatur Hook.

ULIK 17. Nov 2008 14:21

Re: Maus sperren während Tastatureingabe
 
Hallo,
Zitat:

Zitat von blackdrake
Ich habe bei meinem Notebook folgendes Problem: Ich lege meine Handflächen während des Tippens meistens auf die Mitte der Tastatur, was bewirkt, dass ich mit den Handballen ständig auf das (meiner Meinung etwas zu große) Touchpad komme und ich somit während des Tippens ständig in das Textfeld klicke und mein Text dadurch ziemlich verunstaltet wird.

schau Dir doch mal deinen Touchpad-Treiber an. Ich hab ein Uralt-Toshiba und da konnte man das schlicht und ergreifend ausschalten, daß ein Druck auf das Touchpag einen Klick auslöst (und der Treiber war ein Standard für diese Touchpads). Würde mich wundern, wenn modernere Notebooks das nicht haben.

Grüße,
Uli

Sir Rufo 17. Nov 2008 15:28

Re: Maus sperren während Tastatureingabe
 
Ich glaube es geht hier um eine smarte Lösung für das Problem mit dem Touchpad.

Bei Outlook kann ich mit F9 meine emails abholen lassen. Aber das geht auch automatisch.
Den Rechner kann ich ausschalten, wenn ich ihn nicht mehr brauche. Aber das geht mittlerweile auch automatisch (Standby, Ruhezustand).
Bei meinem Auto kann ich alle Türen separat verschließen und öffnen. Die ZV macht das auf einen Schlag.
Mit KeylessGo öffnet und schließt das Auto, wenn ich mich nähere oder entferne.

Es geht nicht darum, dass man da manuell was machen kann, sondern um die smarte Automatik.

Hier in der DP wurde schon mal darauf verlinkt http://www.delphi-treff.de/tutorials...astatur-hooks/

cu

Oliver

SirThornberry 17. Nov 2008 16:46

Re: Maus sperren während Tastatureingabe
 
@Sir Rufo: :thumb:

blackdrake 17. Nov 2008 20:55

Re: Maus sperren während Tastatureingabe
 
Hallo.

@Sir Rufo: Ja, genau so meine ich es. Im Endeffekt will ich das Tool auch veröffentlichen, da es in einigen Situationen bzw. bei einigen Anwendern wirklich sinnvoll ist.

Die Klickfunktion des Touchpads zu Deaktivieren führt natürlich wieder zu einer gezwungenen Umstellung des Benutzers und ist außerdem nicht im Allgemeinen (bei allen Notebooks/Treibern) anwendbar. Und allgemeine Deaktivierungen bzw. per Fn-Tastenkombination sind nur bei längeren Schreibphasen sinnvoll.

Ich habe jetzt mit dem Delphi-Treff-Tutorial folgende Anwendung mit DLL (ich möchte die DLL konventionell extern haben, nicht als Ressource) abgeleitet. Ich bekomme aber eine AV, sobald ich Button 1 oder 2 klicke. Ich weiß nicht, was da passiert :(

Das DP Tutorial ist leider so kompliziert nonVCL geschrieben, dass ich es nur sehr schwer in VCL nachvollziehen/nachmachen kann. Ich denke, dass auch hier ein Problem bei der Transkription besteht.

Hauptanwendung, die ein Keyboard-Ergeigniss erhalten soll

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  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';

procedure TForm1.Button1Click(Sender: TObject);
var
  h: hwnd;
begin
  h := application.Handle; // ???
  InstallHooks(h); // EXCEPTION
  WM_MOUSEHOOKMSG:=getprop(h,mousmsg);
  WM_KEYBHOOKMSG:=getprop(h,keybmsg);
end;

// TODO: Globale Keyboard Message abfragen (mit WM_KEY Message?)

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnInstallHooks; // EXCEPTION
  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, 'InstallHook');
    UnInstallHooks := GetProcAddress(lib, 'UninstallHook');
  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;

end.
Die Hook-DLL, direkt übernommen

Delphi-Quellcode:
library Hooks;

uses
  Windows,
  Messages;

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

var
  Mouse_HookHandle: Cardinal = 0;
  Keyboard_HookHandle: Cardinal = 0;
  WindowHandle: Cardinal = 0;

  WM_MOUSEHOOKMSG: Cardinal = 0;
  WM_KEYBHOOKMSG: Cardinal = 0;

function KeyboardHookProc(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(Keyboard_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, 'keyb_ncode', nCode);
        SendMessage(HWND_BROADCAST, WM_KEYBHOOKMSG, wParam, lParam);
      end;
  end;
end;

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;

function InstallHooks(Hwnd: Cardinal): Boolean; stdcall;
var mouseh, keybh: boolean;
begin
  keybh := false;
  mouseh := false;
//Erstmal Hooks installieren
//First install the hooks
  case Mouse_HookHandle of
    0: begin
        Mouse_HookHandle := SetWindowsHookEx(WH_MOUSE, @MouseHookProc, HInstance, 0);
        SetProp(Hwnd,mousmsg,WM_MOUSEHOOKMSG);
        mouseh := true;
      end;
  end;
  case Keyboard_HookHandle of
    0: begin
        Keyboard_HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0);
        SetProp(Hwnd,keybmsg,WM_KEYBHOOKMSG);
        keybh := true;
      end;
  end;
//Uebergebenes Fensterhandle sichern
//Save the given window handle
  WindowHandle := Hwnd;
  Result := keybh and mouseh;
end;

function UninstallHooks: Boolean; stdcall;
var mouseh, keybh: boolean;
begin
//Hooks aus der Hookchain entfernen
//Uninstall hook from hooks chain
  mouseh := UnhookWindowsHookEx(Mouse_HookHandle);
  keybh := UnhookWindowsHookEx(Keyboard_HookHandle);
  Mouse_HookHandle := 0;
  Keyboard_HookHandle := 0;
  Result := keybh and mouseh;
  if Result then WindowHandle := 0;
end;

exports
//Installations- und Deinstallationsroutine exportieren
//Export the installation and deinstallation routine
  InstallHooks,
  UninstallHooks;

begin
  WM_MOUSEHOOKMSG:=RegisterWindowMessage(mousmsg);
  WM_KEYBHOOKMSG:=RegisterWindowMessage(keybmsg);
end.

Sir Rufo 17. Nov 2008 21:11

Re: Maus sperren während Tastatureingabe
 
Die Anwort auf Deine ??? (Alfred Hitchcock :gruebel: ) aus Zeile 45 der Hauptanwendung findest Du m.E. in Zeile 80 des DLL-Codes:
Delphi-Quellcode:
//Uebergebenes Fensterhandle sichern
//Save the given window handle
  WindowHandle := Hwnd;
cu

Oliver

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?

blackdrake 18. Nov 2008 18:50

Re: Maus sperren während Tastatureingabe
 
Ich habe gerade wieder etwas mit der Mouse+Keyboard-Hook-DLL probiert.

Kann man das auch irgendwie so machen, dass auf die Hook-Message mit "0" geantwortet wird, wenn das Mausereignis gelöscht werden soll?

Delphi-Quellcode:
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 ?
      Message.Result := 0;

      // 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;
In der DLL:

Delphi-Quellcode:
function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  Result := CallNextHookEx(Mouse_HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit;
    FALSE:
      begin
        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);
        if SendMessage(HWND_BROADCAST, WM_MOUSEHOOKMSG, wParam, lParam) = 0 then
        begin
          result := WM_NULL; // Funktioniert das?
        end;
      end;
  end;
end;
Würde soetwas funktionieren oder ist es der falsche Weg? Ich komme mit der Windows API einfach nicht klar...

Apollonius 18. Nov 2008 19:29

Re: Maus sperren während Tastatureingabe
 
Wenn du deine Nachricht an HWND_BROADCAST schickst, kannst du kein Ergebnis erhalten, da die Nachricht an alle Top-Level-Fenster geschickt wird. Deshalb habe ich auch die MMF vorgeschlagen.

Zum Verwerfen der Nachricht zitiere ich mal die MSDN Library:
Zitat:

If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the target window procedure.
Der Rückgabewert ist also keine Nachrichtenkonstante. WM_NULL = 0 ist zum Verwerfen gerade ungeeignet.

blackdrake 18. Nov 2008 19:36

Re: Maus sperren während Tastatureingabe
 
Könntest du bzgl. des MMF ein kleines Beispiel posten, sofern es keine Umstände macht?

Apollonius 18. Nov 2008 19:48

Re: Maus sperren während Tastatureingabe
 
Kein Thema.
Delphi-Quellcode:
//Anwendung
hMapping := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, 4, 'The mapping of the black drake');
pView := MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);

PCardinal(pView)^ := Handle;

//Aufräumen bei Programmende
UnmapViewOfFile(pView);
CloseHandle(hMapping);


//In der DLL
hMapping := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'THe mapping of the black drake');
pView := MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);

TargetHandle := PCardinal(pView)^;

//Aufräumarbeiten bei DLL_PROCESS_DETACH
UnmapViewOfFile(pView);
CloseHandle(hMapping);

blackdrake 18. Nov 2008 21:28

Re: Maus sperren während Tastatureingabe
 
Hallo.

Danke für den Code. Ich werde versuchen, damit den Übertragungsweg zu realisieren.

blackdrake 18. Nov 2008 23:02

Re: Maus sperren während Tastatureingabe
 
Der MMF Übertragungsweg funktioniert nun.

Ein Problem habe ich noch bei der Verwerfung des Mausklicks. Ich verstehe nicht ganz, wie das getan werden soll. WM_NULL ist ja scheinbar falsch, aber was soll dann als Result zurückgegeben werden?

Ausschnitt Anwendung:

Delphi-Quellcode:
procedure TForm1.WndProc(var Message:TMessage);
var
  difference: DWORD;
begin
  if Message.Msg = WM_ANYKEY_PRESSED then
  begin
    inherited WndProc(Message);

    // Eine Taste wurde gedrückt, wir merken uns den Zeitpunkt
    last_keyboard_input := GetTickCount();
  end
  else if Message.Msg = WM_LMOUSECLK_CONFIRM then
  begin
    difference := GetTickCount() - last_keyboard_input;

    if (difference <= sperrdauer) then
    begin
      // Ereignis verwerfen, da linke Maustaste innerhalb
      // der Sperrzeit gedrückt wurde

      // Der DLL melden, dass das Hook die Mausnachricht verwerfen soll.
      Message.Result := 10;

      // 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;
Ausschnitt DLL:

Delphi-Quellcode:
function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  res: Cardinal;
begin
  Result := CallNextHookEx(Mouse_HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit;
    FALSE:
      begin
        // Handelt es sich um einen linken Mausklick?
        if (wParam = WM_LBUTTONDBLCLK) or
           (wParam = WM_LBUTTONDOWN) or
           (wParam = WM_LBUTTONUP) then
        begin
          // Dann Anwendung fragen, ob das OK ist

          SendMessageTimeOut(TargetHandle, WM_LMOUSECLK_CONFIRM, wParam, lParam,
                             SMTO_ABORTIFHUNG or SMTO_BLOCK, MsgTimeOut, res);

          if res = 10 then
          begin
            // Mausklick verwerfen
            Result := WM_NULL; // ToDo: Funktioniert nicht...
          end;
        end;
      end;
  end;
end;
Die "10" ist die Rückantwort, die sagen soll, dass das Mausereignis verworfen werden soll.

Medium 19. Nov 2008 06:58

Re: Maus sperren während Tastatureingabe
 
Das Problem ist wohl, dass du CallNextHook() in jedem Fall aufrufst.
Delphi-Quellcode:
function MouseHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  res: Cardinal;
begin
  case nCode < 0 of
    TRUE: exit;
    FALSE:
      begin
        // Handelt es sich um einen linken Mausklick?
        if (wParam = WM_LBUTTONDBLCLK) or (wParam = WM_LBUTTONDOWN) or (wParam = WM_LBUTTONUP) then
        begin
          // Dann Anwendung fragen, ob das OK ist
          SendMessageTimeOut(TargetHandle, WM_LMOUSECLK_CONFIRM, wParam, lParam, SMTO_ABORTIFHUNG or SMTO_BLOCK, MsgTimeOut, res);
          if res = 10 then // Mausklick verwerfen
            Result := 1 // Irgend ein nicht-null Wert. So hab ich es zumindest auch schon mal gemacht ;)
          else
            Result := CallNextHookEx(Mouse_HookHandle, nCode, wParam, lParam);
          end;
        end;
      end;
  end;
end;
Das einzige was ich jetzt nicht weiss ist, ob und wann nCode jemals <0 wird. Result ist in dem Fall dann undefiniert, und müsste mit einem konstanten Wert vorbelegt werden, der dazu führt dass der Wert von nCode ebenfalls Einfluss darauf hat ob das Ereignis durchkommt oder nicht. Man müsste nur mal schauen unter welchen Bedingungen nCode<0 auftritt.

blackdrake 19. Nov 2008 07:26

Re: Maus sperren während Tastatureingabe
 
Hallo.

Danke für den Tipp, ich werde es später zu Hause gleich ausprobieren.

Ein Verständnisproblem habe ich aber noch: Du sagst, CallNextHookEx() soll nicht aufgerufen werden, wenn ich mein Ereignis verwerfen will, deswegen hast du CallNextHookEx() in die If-Abfrage reingepackt. Klingt logisch. Was ist aber für den Fall dass nCode<0 ist (was das auch immer bedeuten soll)? In meinem vorherigen Code, den ich von Delphi-Treff übernommen habe, wurde CallNextHookEx() auch aufgerufen wenn nCode<0 wäre - war das unrichtig bzw. unnötig?

Gruß
blackdrake

Medium 19. Nov 2008 10:08

Re: Maus sperren während Tastatureingabe
 
Deswegen mein letzter Absatz ;). Ich hatte bei meinem Programm die Abfrage vor, also ausserhalb der nCode-Bedingung, da ich selbst noch in der DLL auf das Event reagieren wollte, aber sonst keiner mehr. Das Problem bei dir ist nun, dass du deine Hostanwendung erst fragen musst ob zu ignorieren ist oder nicht. Wenn du es so biegen kannst dass du es in der DLL direkt entscheiden kannst, dürfte es kein Problem sein das ganze aus dem nCode-Abschnitt zu nehmen. (So langsam wäre es echt interessant zu wissen was nCode angibt. Das msdn fand ich da imho nicht recht hilfreich.)

Bei meinem Programm kann man auch im Host das Ignorieren ab- und anschalten, was mir ein Flag in einem gemeinsamen MMF setzt. Damit entscheide ich dann in der DLL ob geblockt wird oder nicht ohne jedes Mal nachfragen zu müssen. Evtl. wäre das eine Alternative zum Message-Frage-Antwort-Spiel für dich.

Corpsman 19. Nov 2008 11:50

Re: Maus sperren während Tastatureingabe
 
Hi Blackdrage,

ich hatte auch dieses Touchpad Problem und habe es dann mittels automatischem sperren der Maus gelöst, evtl reicht dir das ja auch

Siehe Hier

himitsu 19. Nov 2008 12:19

Re: Maus sperren während Tastatureingabe
 
Zitat:

Zitat von Corpsman
Zusätzlich kann ein Mousehook aktiviert werden, dieser deaktiviert automatisch nach 3 sec. die Linke Maustaste. ... ( nach einem Klick, oder Mausbewegung wird die Linke Maustaste wieder aktiviert )

Was ist, wenn er auch noch ausversehn, beim Schreiben, das Touchfeld berührt und so den Mauszeiger bewegt?
Dann ist die sperre ja wieder raus und er klickt fröhlich weiter wild rum.

Corpsman 19. Nov 2008 14:54

Re: Maus sperren während Tastatureingabe
 
also bei mir hat das Tool wunderbar geholfen.

Denn meistens kommt man tatsächlich nur ganz kurz drauf,

und wenn ihm das Tool nicht hilft kann er sich ja immernoch eins selbst basteln ;).

Ich bin halt der Meinung, wieso selber Proggen wenns eine Freeware auch tut.

Sir Rufo 19. Nov 2008 15:59

Re: Maus sperren während Tastatureingabe
 
Zitat:

Zitat von Corpsman
also bei mir hat das Tool wunderbar geholfen.

Denn meistens kommt man tatsächlich nur ganz kurz drauf,

und wenn ihm das Tool nicht hilft kann er sich ja immernoch eins selbst basteln ;).

Ich bin halt der Meinung, wieso selber Proggen wenns eine Freeware auch tut.

Wenns die Freeware so tut wie man das haben will ... tut es aber nicht ...
Ich finde den Ansatz von blackdrake genau richtig, obwohl in beiden Versionen jeweils eine Annahme zugrunde liegt:

- blackdrake: Nach dem letzten Tastendruck (ausgenommen STRG) kann ich 3 Sekunden mein Touchpad vergessen
- Corpsman: "Denn meistens kommt man tatsächlich nur ganz kurz drauf,"

Da der Ansatz von blackdrake immer so funtioniert (funzen soll) kann sich der Anwender drauf einstellen oder am Zeitintervall etwas drehen.

Bei deinem Ansatz kann es völlig unkontrolliert und vom Anwender nicht wirklich nachvollziehber (sonst bräuchten wir so ein Programm eh nicht) trotzdem zu ungewollten Reaktionen kommen, die das Prgramm ja eigentlich verhindern soll.

Es ist etwas anderes, ob ich eine Funktionsweise erwarte oder ob diese mich überrascht.
Und eine Lösung die von Konzept her 100% funktioniert ist dann besser als eine die im Konzept Schwächen hat.

Es geht dabei nicht um die Umsetzung - das kann ich nicht beurteilen - aber den Ansatz.

cu

Oliver

Corpsman 19. Nov 2008 17:28

Re: Maus sperren während Tastatureingabe
 
@ sir,

Ist ja nett das du hier deine Meinung dagegen vorträgst, die Argumente will ich auch gar nicht bewerten, jedoch wärs nett wenn du einen Lösungsansatz postest, sonst hast du hier nur "heise Luft" verblasen ...

Sir Rufo 19. Nov 2008 17:44

Re: Maus sperren während Tastatureingabe
 
@Corpsman: ich habe meine Meinung als direkte Antwort von Deiner Meinung geschrieben (war auch kein Code dabei)

so wie auch hier meine Meinung ...

so what

Oliver

if u want to have code look here :mrgreen:

blackdrake 19. Nov 2008 20:21

Re: Maus sperren während Tastatureingabe
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo.

Danke für eure Beiträge. Das Tool habe ich nicht ausprobiert, da es mir zu statisch vorkommt. Außerdem bin ich ja gerade dabei, ein eigenes kleines Tool zu schreiben, bei dem ich außerdem noch einiges über die WinAPI dazulerne.

Ich habe jetzt folgendes gemacht:

- Die DLL prüft nun intern, ob die Maustaste erlaubt ist oder nicht, deswegen ist jetzt kein "Frage-Antwort-Spiel" mit der Host-Applikation mehr nötig.

- Die DLL übergibt der Host-Applikation folgende Messages, die z.B. für grafische Ereignisse/Hinweise verwendet werden können:

* WM_LMB_LOCKED -- die linke Maustaste ist ab jetzt gesperrt (Host-App soll Systemzeiger in crNo verändern)
* Nach 3 Sekunden kommt dann automatisch: WM_LMB_UNLOCKED -- die linke Maustaste ist ab jetzt wieder freigeschaltet (Host-App soll den Systemzeiger wiederherstellen)
* WM_LMB_BLOCKED -- eine linke Maustaste wurde innerhalb der Sperrzeit gedrückt. Das Ereignis wurde geblockt! (z.B. Sound-Ereignis abspielen)

Aber es existieren folgende Bugs, bei denen ich nicht weiterkomme:

1. Host-App: Der Mauszeiger wird nicht nach crNo mittels SetSystemCursor() innerhalb der WndProc() geändert! Außerhalb der WndProc() funktioniert es seltsamerweiße!

Delphi-Quellcode:
procedure TForm1.WndProc(var Message:TMessage);
begin
  if Message.Msg = WM_LMB_BLOCKED then
  begin
    label2.Caption := 'WM_LMB_BLOCKED ' + IntToStr(GetTickCount());
  end
  else if Message.Msg = WM_LMB_LOCKED then
  begin
    label1.Caption := 'WM_LMB_LOCKED';

    // BUG 1!!! Mauszeiger verändern funktioniert nicht

    cursor_backup := GetCursor;
    SetSystemCursor(Screen.Cursors[crNo], OCR_NO);
  end
  else if Message.Msg = WM_LMB_UNLOCKED then
  begin
    label1.Caption := 'WM_LMB_UNLOCKED ' + IntToStr(GetTickCount());

    SetSystemCursor(cursor_backup, OCR_NORMAL);
  end;

  inherited WndProc(Message);
end;
2. DLL: Die Kontrolle, ob eine Strg-Taste gedrückt ist, funktioniert nicht!

3. DLL: Der (einmalige) Timer, der nach WM_LMB_LOCKED (neu)gestartet wird und nach 3 Sekunden zu WM_LMB_UNLOCKED führen soll, funktioniert nicht! Er funktioniert nur, wenn man innerhalb der Host-Anwendung Tasten drückt. Tippt man in Notepad etwas ein, dann ist der Timer gleich 0.

Delphi-Quellcode:
var
  lock_interval: Integer; // wird bei dem DLL-Start gesetzt bzw. mit einer externen DLL-Funktion aktualisiert
  last_timer: Cardinal;

procedure timerevent;
var
  res: Cardinal;
begin
  // Es soll ein einmaliger Timer sein
  KillTimer(0, last_timer);
  last_timer := 0;

  SendMessageTimeOut(TargetHandle, WM_LMB_UNLOCKED, 0, 0,
                     SMTO_ABORTIFHUNG or SMTO_BLOCK, MsgTimeOut, res);
end;

function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  res: Cardinal;
begin
  Result := CallNextHookEx(Keyboard_HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit;
    FALSE:
      begin
        // BUG 2!!! VK_CONTROL-Kontrolle funktioniert nicht!

        // Strg+Maustaste ist legitim für Mehrfachselektion
        if GetKeyState(VK_CONTROL) = 0 then
        begin
          last_keyboard_input := GetTickCount();

          SendMessageTimeOut(TargetHandle, WM_LMB_LOCKED, 0, 0,
                             SMTO_ABORTIFHUNG or SMTO_BLOCK, MsgTimeOut, res);

          // Jetzt: 3 Sekunden warten und dann WM_LMB_UNLOCKED senden, ggf. vorherigen Timer zurücksetzen

          // BUG 3!!! Dieser Timer funktioniert nur, wenn man in der Anwendung
          //          was tippt. Tippt man z.B. im Notepad, hat der Timer
          //          ein Interval von 0 statt 3000.

          // Den vorherigen Timer zurücksetzen
          if last_timer <> 0 then KillTimer(0, last_timer);
          last_timer := SetTimer(0, IDC_TIMER1, lock_interval, @timerevent);
        end;
      end;
  end;
end;
Könnt ihr mit bitte weiterhelfen? Ich habe bei diesen 3 Bugs keine Lösung erzielen können.

Wenn ihr nochwas im Projekt findet, schreibt mir bitte Vorschläge!

Gruß
Daniel Marschall

Apollonius 19. Nov 2008 20:43

Re: Maus sperren während Tastatureingabe
 
Mit SetTimer und KillTimer bist du in einer DLL zu unflexibel. Wenn du für den ersten Parameter Null einsetzt, spielst du Vabanque. Du gehst nämlich davon aus, dass alle Applikationen, die die DLL geladen haben, eine Nachrichtenschleife haben. Wie die Nachrichten-Weitergabe bei einem Null-Handle passiert, ist mir selbst noch nicht ganz klar.

Ich würde auf Waitable Timer umsteigen. Erstelle dir einen neuen Thread, der nur auf den Timer warten und beim Ablaufen die Unblocked-Nachricht versendet. Schau dir dazu mal MSDN-Library durchsuchenCreateWaitableTimer und MSDN-Library durchsuchenSetWaitableTimer an.


Aber zuletzt noch etwas anderes: Ich hielt die vorige Lösung für besser, in der ein zentrales Programm steuert, ob Mausereignisse blockiert werden. Andernfalls musst du nämlich eine ganze Menge Daten in die MMF schreiben, damit die DLLs immer synchron arbeiten und nicht eine Instanz Ereignisse durchlässt und eine andere blockiert.

blackdrake 19. Nov 2008 20:51

Re: Maus sperren während Tastatureingabe
 
Zitat:

Zitat von Apollonius
Mit SetTimer und KillTimer bist du in einer DLL zu unflexibel. Wenn du für den ersten Parameter Null einsetzt, spielst du Vabanque. Du gehst nämlich davon aus, dass alle Applikationen, die die DLL geladen haben, eine Nachrichtenschleife haben. Wie die Nachrichten-Weitergabe bei einem Null-Handle passiert, ist mir selbst noch nicht ganz klar.

Ich würde auf Waitable Timer umsteigen. Erstelle dir einen neuen Thread, der nur auf den Timer warten und beim Ablaufen die Unblocked-Nachricht versendet. Schau dir dazu mal MSDN-Library durchsuchenCreateWaitableTimer und MSDN-Library durchsuchenSetWaitableTimer an.

OK, probiere ich mal.

Zitat:

Zitat von Apollonius
Aber zuletzt noch etwas anderes: Ich hielt die vorige Lösung für besser, in der ein zentrales Programm steuert, ob Mausereignisse blockiert werden. Andernfalls musst du nämlich eine ganze Menge Daten in die MMF schreiben, damit die DLLs immer synchron arbeiten und nicht eine Instanz Ereignisse durchlässt und eine andere blockiert.

Es gibt aber nur 1 DLL und 1 Host-Anwendung für den Automatic-Touchpad-Locker. Deswegen muss da doch nichts synchron sein, oder? Und da finde ich es besser, wenn die DLL intern den Keyboard-Hook und den Mouse-Hook miteinander verbindet. Das Problem bei der vorherigen Variante war nämlich dies: Stürzt die Anwendung ab oder hängt sie und sollte die DLL ihre Hook-Funktion fortsetzen, dann würde jeder Mausklick 10 Sekunden verspätung bekommen, weil das der Timeout für die Message "Darf Maustastendruck ausgeführt werden?" an die nicht mehr existierende/hängende Host-Applikation. Sehe ich das richtig?

Apollonius 19. Nov 2008 20:57

Re: Maus sperren während Tastatureingabe
 
Zitat:

Zitat von blackdrake
Es gibt aber nur 1 DLL und 1 Host-Anwendung für den Automatic-Touchpad-Locker.

Tatsächlich? Die DLL muss doch in jede Anwendung einzeln geladen werden.

Hast du das Problem mit der abgestürzten Anwendung wirklich getestet?.
Zitat:

SMTO_ABORTIFHUNG
Returns without waiting for the time-out period to elapse if the receiving thread appears to not respond or "hangs."
Du solltest allerdings den Rückgabewert von SendMessageTimeout überprüfen, um Timeouts zu erkennen.

blackdrake 19. Nov 2008 21:03

Re: Maus sperren während Tastatureingabe
 
Mehrere DLL-Instanzen? Bedeutet das etwa folgendes?

- Host-Anwendung Project1.exe startet StartLocker() der DLL (dort wird der Hook gestartet und Variablen gesetzt).
- Sobald ich in Notepad etwas tippe, öffnet Notepad nochmal die DLL?
Woher weiß Notepad aber, dass in meiner DLL StartLocker() gestartet werden muss?

Dann wäre die Verwaltung über die zentrale Host-Applikation über die eindeutige GUID doch besser. :|


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:23 Uhr.
Seite 1 von 2  1 2      

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