Key abfragen ohne OnKeyDown/Up/Press Events

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Hallo, ich bins mal wieder mit einer neuen Frage.

Mein Probem:
Um mein Bild immer und immer wieder zu zeichnen muss ich das OnIdle Event benutzen. Jetzt möchte ich aber die zeichenschleife durch das Drücken von ESC unterbrechen. Im IdleHandler muss dann sowas kommen wie:

Code: Alles auswählen

if ESC = False 
  then Draw
  else MachWasAnderes;
Ich habe es bereits mit GetKeyState(VK_ESCAPE) probiert. Das Problem ist, dass hier nicht unterschieden wird, ob die Taste immer noch gedrückt ist oder erneut gedrückt wurde. Das heißt man kann glück haben, dass man genau rechtzeitigt die Taste loslässt um ESC nicht erneut auf False zu setzten.

Ich suche im Prinzip nach einer funktion, die schaut ob eine Taste losgelassen wurde.

Durch das OnIdle event funktioniert leider das OnKeyUp event nicht mehr. Ich kann die Escape Taste drücken wie ich will, es kommt nicht bei Lazarus an.

Ich hoffe ihr wisst eine Lösung für das Problem

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6209
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von af0815 »

Wieso OnIdle ? Zeichnen wird im OnPaint erledigt. Überall anders ein Invalidate.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Ich habe ein OpenGL Projekt. Die ogcDraw wird von dem IdleHandler ausgelöst. Im IdleHandler lasse ich zudem die Framerate für DeltaTime berechnen

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Mathias »

Als Alternative, kann man auch einen Timer benutzen.
Hier habe ich genügen Beispiele.

https://github.com/sechshelme/Lazarus-O ... 3-Tutorial
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Dadurch wird das Bild genauer und flüssiger

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Mathias »

Aloxen hat geschrieben:
So 27. Nov 2022, 22:38
Dadurch wird das Bild genauer und flüssiger
Meinst du jetzt mit Idle oder mit dem Timer ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Mit OnIdle. Als ich OpenGL getestet und an den Shadern geknabbert habe habe ich auch einen Timer benutzt aber in den Gameengines gibt es einen Fixed Timer und einen eine Draw, die auf der Geschwindigkeit des Rechners basiert.

Ich möchte die OnIdle eigentlich nicht raus nehmen, weil ich gerade meinen ganzen Code auf ein TimeBasedMovement umgestellt habe und es die Berechnung für unterschiedliche Hardware genauer macht.

Ich suche nach einem Weg trotz der OnIdle einfache Tastatur Eingaben abzufragen. Ich hatte überlegt, dass ich die OnIdle, die mit GetKeyState(VK_ESCAPE) überprüfen kann, ob Escape gedrückt wurde, die OnIdle zu beenden und somit auch die Abfrage von GetKeyState. Die Frage ist, ob dass funktionieren kann und wenn, wie würde ich das machen? Bisher habe ich Application.OnIdle:=nil; Aber damit wird es nicht ganz beendet, sondern nur kurz. Das Bild steht kurz und danach geht alles weiter. Application.OnIdle := @IdleHandler habe ich nur einmal am Anfang geschieben, sie wird nicht vom IdleHandler aufgerufen

Könnte es so funktionieren und oder gibt es noch andere Wege wie ich KeyUp manuell abfragen kann?

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von theo »

Ich verstehe das nicht wirklich.
Für meine Begriffe wird OnIdle dann aufgerufen, wenn die Anwendung "nichts Besseres" zu tun hat, bzw. wenn die Message Queue leer ist.
Für flüssiges (prioritäres) Zeichnen käme mir das nicht nicht in den Sinn.

Ich würde es eher umgekehrt machen: In einen Loop gehen und mit Application.Processmessages die Messages abarbeiten.

Jedenfalls in der Theorie. In der Praxis weiss ich's nicht.

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Na ja, ich nutze die ObIdle, weil das Programm immer Zeichnen soll, wenn es gerade nichts zu tun hat. Deshalb die OnIdle

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Hi ich bin es nochmal. Also das On Idle Event ist wirklich nicht praktisch, aber dadurch dass so oft gezeichnet wird, ist das Bild sehr flüssig.
ProcessMessages habe ich so verstanden, dass wenn es im Code ausgeführt wird, der Computer alle Messages die angekommen sind liest und ausführt. Also auch ein KeyUp.

Wie mache ich jetzt daraus ein loop, der immer wenn einmal gezeichnet wurde wieder von neuem zeichnet?

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Winni »

Hi!

also:

* Gezeichnet wird in OnPaint
* Eine Boolsche var in der TForm1 definieren, z.B. ESCpressed
* OnKeyup: wenn ESC, dann ESCpressed setzen
* OnPaint: Zeichnen, wenn nicht ESCpressed else ESCpressed zurücksetzen
* loop:

Code: Alles auswählen

Repeat
Image1.invalidate; //oder worauf Du zeichnest
Application.ProcessMessages; // keyup und paint verarbeiten
sleep (50); // optional
until false;
So müssten deine "strange desires" funktionieren.

Noch ein bischen Code, um die Endlosschleife abzubrechen ...

Winni

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Hi also das zeichnen funktioniert einwandfrei, aber das OnKeyUp event wird trotzdem nicht erkannt. Das ist mein key up und das mein Form paint:

Code: Alles auswählen

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_E then Form4.ShowModal;
  if key = VK_ESCAPE then EscMenu;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
 Repeat
   if ESC=false then ogc.invalidate; //oder worauf Du zeichnest
   Application.ProcessMessages; // keyup und paint verarbeiten
until false;
end; 

procedure TForm1.EscMenu;
begin
  if Esc = false
   then
    begin
      Esc:=True;
      ShowOptionsMenu;
    end
   else
    begin
      Esc:=false;
    end
end;

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Soner »

Key-Abfragen macht man mit GetKeyState. Hier ein Beispiel:

Code: Alles auswählen

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, LCLType, LCLIntf;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
   if ((GetKeyState(VK_ESCAPE) and $8000) <> 0) then Caption:='Escape'
   else caption:='kein Escape';
end;

end.   

In deinem Fall must du die Prozeduren FormKeyUp, EscMenu komplett löschen und deine Schleife ändern in:

Code: Alles auswählen

procedure TForm1.FormPaint(Sender: TObject);
var Beenden: boolean;
begin
  Beenden:= false;
  Repeat
    if ((GetKeyState(VK_E) and $8000) <> 0) then Form4.ShowModal;
    if ((GetKeyState(VK_ESCAPE) and $8000) <> 0) then ShowOptionsMenu;
	Beenden:=((GetKeyState(VK_Q) and $8000) <> 0); //als bespiel um schleife zu beenden
  
    ogc.invalidate; //oder worauf Du zeichnest
    Application.ProcessMessages; // keyup und paint verarbeiten
	
	sleep(10); //füge in die schleife immer sleep, sonst drehen die lüfter hoch
	           //man merkt den unterschied nicht
  until Beenden;
end; 


Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Winni »

@ Aloxen

Hi!

Da geht ja einiges Durcheinander bei Dir.

Ich hab Dir ne kleine Demo gemacht - anbei.

Die zeichnet alle halbe SEkunde ein fünfzackiges Polygon auf eine Paintbox - es sei denn, Du hast ESC gedrückt. Dann erscheint einmal ESC auf dem Bildschirm.

Sieh Dir den Code in Ruhe an und dann überlege, wie Du ihn für Deine Zwecke umbauen kannst,

Grüße
Winni
Dateianhänge
Keypress.zip
(360.47 KiB) 63-mal heruntergeladen

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Key abfragen ohne OnKeyDown/Up/Press Events

Beitrag von Aloxen »

Winni hat geschrieben:
Sa 10. Dez 2022, 19:42
Ich hab Dir ne kleine Demo gemacht - anbei.
Leider kann ich das Projekt nicht ausführen. "Kann LCLBase nicht finden verwendet von KeyP1"

Antworten