Einzelnen Beitrag anzeigen

blackdrake

Registriert seit: 22. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#36

Re: Maus sperren während Tastatureingabe

  Alt 19. Nov 2008, 21:21
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
Angehängte Dateien
Dateityp: zip neuer_zip-komprimierter_ordner_182.zip (326,5 KB, 6x aufgerufen)
Daniel Marschall
  Mit Zitat antworten Zitat