Delphi - Anweisung pro Tastendruck nur einmal

Hi.
Zunächst - ich programmiere in Delphi.

Ich möchte einen Tastendruck zur Laufzeit regestrieren und dann ein paar Anweisungen ausführen lassen. Also hab ich den Code für den Tastendruck etc. in nen Timer mit dem Intervall von "1" reingeschrieben, woanders macht es ja wenig Sinn, da es ja ständig abgefragt werden soll.

Vereinfacht dargestellt:

Code:
IF (GetAsyncKeystate(vk_LCONTROL)) < 0
THEN
begin
ListBox1.Items.Add(Text);
etc.
etc2.
end;

Das Problem (bei diesem Beispiel) das ich nun habe ist, dass nun der Text selbst bei kurzem antippen der Strg-Taste oft in die Listbox eingefügt wird. Kurz gesagt: Die Anweisungen sollen nur _einmal_ ausgeführt werden (pro Tastendruck).

Wie kann ich das lösen ?
Durch irgendwas besonderes was ich in den Timer reinschreibe, oder muss ich gleich ne ganz andere Komponente verwenden ? Wenn "ja" welche ?

Vielen Dank für Antworten.
 
Eigentlich war meine erste Idee einen Zähler einzubauen, der eben mitzählt, ob die Taste schon losgelassen wurde, aber es gibt auch eine andere Variante:

http://msdn.microsoft.com/library/e...nputfunctions/getasynckeystate.asp?frame=true
If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.

Ansonsten: eine zusätzliche Variable, z.B Key_up, die eben in Deiner Routine (Reaktion auf keydown) auf false gesetzt wird - und nur wenn man die Taste wieder loslässt, auf True - so kannst Du in der "Reaktionsroutine" abfragen, ob die Taste schon vorher losgelassen wurde oder der Tastendruck noch immer andauert.

Code:
if (get_keystate(x)=down) AND (key_up=true)  then
  begin
     mache irgendwas;
     key_up:=false;
  end;

if getkeystate(x)=up then key_up:=true;
 
Original von CDW

if (get_keystate(x)=down) AND (key_up=true) then
begin
mache irgendwas;
key_up:=false;
end;

if getkeystate(x)=up then key_up:=true;

Das widerspricht sich doch...
Pseudo Code:
WENN Keystate = Down UND Key_up = True DANN ...

Key_up IST TRUE WENN Keystate = up IST


Damit widersprechen sich doch die Forderungen oder ?!
Edit:
Naja ich hab nach dem Schema auch noch etwas rumprobiert es aber nicht hinbekommen. Hab noch ein paar Links wo ich schon dachte die Lösung zu haben aber es funktioniert auch nicht.
Info:
http://www.dsdt.info/tipps/?id=28
und
http://www.dsdt.info/tipps/?id=208


Vielen Dank aber für die Antwort.
Bis Morgen Abend, ich geh heiern.
 
Damit widersprechen sich doch die Forderungen oder ?!
hm, eigentlich nicht (dass ich das sehe ;) ) - denn sie werden unabhängig voneinander ermittelt. Der Sinn ist eben festzustellen, ob die taste vorher losgelassen wurde - so ähnlich habe ich das auch mal gemacht (nur eben eine etwas andere Sprache). Ich hatte die Feuertaste und wollte den Laser unbediengt nur einmal pro Tastendruck (und nicht 30mal die Sekunde - sooft die abgefragt wurde) abfeueren.

so sah das aus ( ist eigentlich MASM, ein wenig jetzt in den Pseudocode-Status editiert, die 1 und 0 kann man auch einfach durch TRUE/FALSE ersetzen, werde mich jetzt aber um diese Uhrzeit hüten, da großartig rumzueditieren ;) ):

Code:
pushed:=GetKeyState,VK_SPACE 
     
     .if (pushed==TRUE) &&( messages.laser_flag==0)       
        
          messages.laser_flag:=1;

         .if messages.feuer==0
                 messages.feuer:=1
         .else
         	 messages.feuer:=messages.feuer+1	;wenn taste weiterhin gedrückt wird, nur als 1 Schuss zählen
         .endif         
      	 PlaySound,305,hInstance,SND_RESOURCE+SND_ASYNC
     .elseif (state==FALSE)  
     	 messages.laser_flag:=0   
     	 messages.feuer:=0  	
     .endif

Es funktioniert jedenfalls - auch wenn Du bestimmt keine zwei Variablen bräuchtest. Werde es mir morgen noch mal anschauen (kann auch sein dass noch mehr Leute vorbeikommen ;) )
 
Du hast ja anscheinend nen Timer laufen.

timerprozedur();
begin
knopfdruckbedingung();
end;

Nun willst du wissen ob im letzten Frame der Timer gedrückt war.
Also setzt du eine unterbedingung: Nur auslösen, wenn im letzten Frame nicht gedrückt war.

timerprozedur();
begin
knopfdruckbedingung(parameter);
imletztenframegedrückt:=GetKeyState();
end;

wobei dann knopfdruckbedingung aus if(imletztenframedgedrückt=false) and (aberjetztgedrückt=true) then..

Achja bei Delphi gibts bei den Ereignissen allerdings ne einfachere Lösung. Ich gehe mal davon aus, dass du auf einer Form rumhantierst und nicht in DirectX oder so.
Da wo du OnCreate etc. findest gibts auch OnKeyDown OnKeyPress etc.. da ist der mechanismus schon eingebaut.
 
Zurück
Oben