Delphi-PRAXiS
Seite 4 von 6   « Erste     234 56      

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)

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 09:05 Uhr.
Seite 4 von 6   « Erste     234 56      

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