Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 17, 2025 23:15

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Tastenabfrage
BeitragVerfasst: Di Mai 22, 2007 15:34 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
hi, bisher verwendete ich für das abfragen meiner tasten das onkeyup bzw das onkeydown des formulurares.
jetzt habe ich diverse komponenten auf dem formular und trotz keypreview := true tut sich bei mir rein gar nischt.

vorher sah der code so aus
Code:
  1.  
  2. procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
  3.   Shift: TShiftState);
  4. begin
  5.   if key = vk_left then
  6.   begin
  7.     kright := false;
  8.     kleft := true;
  9.   end;
  10.   if key = vk_right then
  11.   begin
  12.     kleft := false;
  13.     kright := true;
  14.   end;
  15.   if key = vk_up then
  16.   begin
  17.     kdown := false;
  18.     kup := true;
  19.   end;
  20.   if key = vk_down then
  21.   begin
  22.     kup := false;
  23.     kdown := true;
  24.   end;
  25. end;
  26.  
  27. procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word;
  28.   Shift: TShiftState);
  29. begin
  30.   if key = vk_left then
  31.     kleft := false;
  32.   if key = vk_right then
  33.     kright := false;
  34.   if key = vk_up then
  35.     kup := false;
  36.   if key = vk_down then
  37.     kdown := false;
  38. end;
  39.  


jetzt habe ich diesen durch folgenden ersetzt:
Code:
  1.  
  2. procedure TMainForm.KeyCheck;
  3. begin
  4.   if boolean(getasynckeystate(vk_left)) then
  5.   begin
  6.     kleft := true;
  7.     kright := false;
  8.   end else
  9.     kleft := false;
  10.   if boolean(getasynckeystate(vk_right)) then
  11.   begin
  12.     kright := true;
  13.     kleft := false;
  14.   end else
  15.     kright := false;
  16.   if boolean(getasynckeystate(vk_up)) then
  17.   begin
  18.     kup := true;
  19.     kdown := false;
  20.   end else
  21.     kup := false;
  22.   if boolean(getasynckeystate(vk_down)) then
  23.   begin
  24.     kdown := true;
  25.     kup := false;
  26.   end else
  27.     kdown := false;
  28. end;
  29.  


allerdings ist jetzt die bewegung langsam und stockend und diagonale bewegungen gehen nicht mehr, woran kann das liegen ?

aufgerufen wird das ganze im onidle:
Code:
  1.  
  2.   CalcTimeStep;
  3.  
  4.   keycheck;
  5.  
  6.   // Bewegung
  7.   if kleft then
  8.     offset.x := offset.x + 500 * timestep;
  9.   if kright then
  10.     offset.x := offset.x - 500 * timestep;
  11.   if kup then
  12.     offset.y := offset.y + 500 * timestep;
  13.   if kdown then
  14.     offset.y := offset.y - 500 * timestep;
  15.  


um offset wird dann mittels glTranslatef verschoben.

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 17:14 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Jan 31, 2005 11:02
Beiträge: 432
Wohnort: Rheinlandpfalz
Hi,
Erstmal zur Vereinfachung der Tastenabfrage würde ich dir folgende Methode empfehlen:
Code:
  1. Var keys : Array [0..255] of boolean;
  2.  
  3. procedure TMainForm.FormKeyDown(Sender:TObject; var Key:Word; Shift:TShiftState);
  4. begin
  5.   keys[key] := true;
  6. end;
  7.  
  8. procedure TMainForm.FormKeyUp(Sender:TObject; var Key:Word; Shift:TShiftState);
  9. begin
  10.   keys[key] := false;
  11. end;
  12.  
  13. Procedure TMainForm.OnIdle;
  14. Begin
  15.   IF (keys[VK_LEFT])  Then offset.x := offset.x + 500 * timestep;
  16.   IF (keys[VK_Right]) Then offset.x := offset.x - 500 * timestep;
  17.   IF (keys[VK_UP])    Then offset.y := offset.y + 500 * timestep;
  18.   IF (keys[VK_DOWN])  Then offset.y := offset.y - 500 * timestep;
  19. End;


Wenn du mehrere Komponenten auf der Form hast zB. Buttons etc. greift die FormKeyDown / FormKeyUp Methode nicht mehr,
sobald eines der Komponenten den Focus hat. Das Problem habe ich selber nicht wirklich gelöst, ich habe es dann so gemacht,
dass ich die Komponenten die ich benötigt habe mit meiner OGL-Gui gezeichnet habe...
Falls ich dein Problem richtig verstanden habe, hoffe ich dir ein wenig geholfen zu haben :wink:

_________________
http://texelviews.delphigl.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 18:28 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
leider möchte ich die komponenten net auf das gl fenster zeichnen, das ist das problem ;) und getasynckeystate funzt zwar, verursacht aber die oben genannten probleme Oo

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 18:39 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Hallo Seth,
ich hab es grade ausprobiert: Wenn Du bei allen Komponenten, die Du auf Deinem Form draufhast, die Eigenschaft "Tabstop" auf "False" setzt dann empfängt das Fenster wieder Tastendrücke; KeyPreview muss nicht True sein. Weiß jetzt nicht ob es auch anders geht.
Traude


EDIT: Es geht doch nicht. Denn wenn man mit der Maus eine Komponente anklickt, kriegt dieses den Focus und läßt ihn nicht mehr los. Ich habe das in einem früheren Projekt implementiert und habe mir damals folgende Notizen dazu gemacht:

//********************************************************************
// Das Map-Panel kann die CursorTasten nicht auffangen,
// daher müssen die Tastenanschläge vom Formular gelesen werden:
// 1. Das Ereignis KeyDown muss vom Formular behandelt werden
// 2. KEIN EINZIGES Steuerelement darf TabStop = True haben
// 3. KEYPREVIEW des Formulars muss FALSE sein
// 4. Die Ereignisbehandlungsmethode OnMouseMove des MapPanel muss alle
// Panels defokussieren, die einen Fokus erhalten können ("DefocusControl")


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 19:07 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
ich werde das versuchen, aber warum funktioniert die variante mit getasynckeystate nicht richtig ? wäre das nicht der "bessere" weg ?

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 19:17 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Bin mir da gerade nicht 100%tig sicher aber alternativ sollte man auch auf einem Panel rendern können. Wenn man dieses etwas anpasst. Also so, dass es einen Fokus bekommen kann, dann verhält es sich wie eine Komponente und bekommt alle Tasten mit. Natürlich nur sofern es fokusiert wurde. Aber sonst ist ja auch der Button XYZ aktiv und soll auf die Leertaste etc. reagieren.

Ich habe das mal auf meine Seite geladen. Das ist aber so ausgelegt, dass man im OnPaint rendert, da es nicht für eine Renderschleife konzipiert wurde. Ist vom Code her nichts berauschendes. Aber dann verhält sich die OpenGL Ansicht wie eine Komponente. Na ja. Ist ja auch eine.

AdvancedPanel 3KB.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 19:23 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
@Seth: Tut mir leid, das weiß ich leider nicht. Aber GetAsyncKeystate ist eine WINAPI-Funktion und Du mischt daher hier VCL und WINAPI, vielleicht ist das der Grund. Aber, wie gesagt, ich weiß es nicht.

@Lossy: Bei dem Beispiel oben rendere ich mit OpenGL auf einem Panel, habe aber noch zahlreiche andere VCL-Panels mit Knöpfen drauf (es ist ein Spiele-Editor).

EDIT: Lossy: Wie hast Du das gemacht? Das TPanel hat kein OnKeyDown-Ereignis. Hast Du ihm eines implementiert?

nochmal EDIT: Ich hab mir das AdvancedPanel angesehen: Nicht schlecht. Ich kann mich erinnern, damals mit den Ereignissen für den Spiele-Editor ganz schön gerauft zu haben.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 19:54 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
also ich rendere auf ein panel, wie könnte ich das mit deinem panel beheben ?

und verwechseln tue ich nichts, schau dir den source an, das eine ist im onidle, das andere im onkeyup / down, zwei verschiedene methoden. das eine ist ein ereignis und das andere ist ne statusabfrage im onidle

mfg


Zuletzt geändert von Seth am Di Mai 22, 2007 20:02, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 19:55 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Das TCustomPanel bietet schon die Ereignisse OnKeyDown/Up bzw irgendeine Klasse davor und die Ereignisse mache ich nur sichtbar.

Code:
  1.   published
  2.     ...
  3.     property OnKeyDown;
  4.     property OnKeyPress;
  5.     property OnKeyUp;


Aber das Standardpanel kann keinen Focus bekommen weswegen der auch keine richtigen Tastaturevents bekommt bzw sich nicht vor die anderen Komponenten "drängeln" kann.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 20:11 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
mit dem advanced panel funzt das super danke ;)
allerdings zeichne ich darauf immernoch wie ein normales panel, "darf" ich das, oder kann das zu komplikationen führen ? Bisher läuft das ohne Probleme :?

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Mai 22, 2007 20:19 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Das ist ein normales Panel. Nur, dass es das ein oder andere mehr hat. Also Fokus/Tastatur und EraseBackground wird nicht mehr durchgeführt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 14, 2007 23:52 
Offline
DGL Member

Registriert: Fr Feb 23, 2007 12:51
Beiträge: 2
Wohnort: In meiner Dunklen ecke
Was ist der unterschied zwischen getasynckeystate(vk_left) und getkeystate(vk_left)?

Ich hab in einem kleinem Programm mal die verwendung von:

Code:
  1. if getkeystate(vk_left) > 0 then begin
  2. xxxxxx
  3. end;


Hab mir die funktion getkeystate mal angeschaut und die liefert abwechselnd den wert 128 und 127 wenn die taste unten ist und 0 -1 wenn nicht (soweit ich mich richtig erinnere)

Vieleicht ist es wenn du es so machst weniger laggy =D (Vieleicht)

_________________
>.< Ich bin nicht Krank ich bin nur anders >.<


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Aug 15, 2007 11:28 
Offline
DGL Member

Registriert: Di Jun 06, 2006 09:59
Beiträge: 474
get keystate setzt das bit 7(128) wenn die taste gedrückt ist. Jeden 2. druck setzt es das bit 0(1)was nur für capslock etc interessant ist. Also kannst du mit (getkeystate(keycode) and 128<>0) feststellen ob eine taste gerdückt ist. GetAsyncKeystate liefert zurück ob die taste gerade gedrückt ist, und ob sie seit dem letzen aufruf von getasynckeystate mit diesem Parameter in diesem Thread gedrückt war. Welche Bits dafür zuständig sind kannst du entweder in der Win32 Hilfe von Delphi oder der MSDN nachlesen.

_________________
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Aug 15, 2007 11:43 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
GetAsyncKeystate liefert außerdem den direkten Status der Taste wie sie gerade ist (praktisch "Hardware" status). GetKeyState hingegen hängt irgendwie davon ab ob die entsprechende Nachricht schon von der Anwendung verarbeitet wurde. Wenn man z.b. einen Tastatur Hook gesetzt hat KANN es passieren das GetKeyState im Hook den falschen status zurück gibt, GetAsyncKeyState hingegen funktioniert immer.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 14 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 15 Queries | GZIP : On ]