Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Mehrere Objekte aufeinmal, mit versch. Tastenkombinationen


Lernenochdazu - Mo 11.07.22 08:58
Titel: Mehrere Objekte aufeinmal, mit versch. Tastenkombinationen
Guten Tag,

Ich habe eingestellt, dass ich mit w und s, sowie up und down ein shape bewegen kann. Allerdings kann ich beide shapes, wenn ich z.B w und down drücke, nicht zusammen bewegen. Nur abwechselnd. Welche Möglichkeiten habe ich, damit beides gleichzeitig geht?

LG

Moderiert von user profile iconTh69: Titel leicht geändert (war "Mehrere Objekte aufeinmal, mit verschiedenen Tastenkombinati").
Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Di 12.07.2022 um 07:46


jaenicke - Mo 11.07.22 09:00

An der Stelle, an der du das eine Shape bewegst, kannst du doch auch das andere mit bewegen.

Ohne zu wissen wie du das machst, kann ich aber nichts Genaueres dazu sagen.


Lernenochdazu - Mo 11.07.22 09:13

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
An der Stelle, an der du das eine Shape bewegst, kannst du doch auch das andere mit bewegen.

Ohne zu wissen wie du das machst, kann ich aber nichts Genaueres dazu sagen.


Das andere Shape soll aber mit anderen Tastenkombinationen bewegt werden. Nicht mit den gleichen.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
     
     if (key = Ord('W')) and (beispiel1.Top > irgendwasanderes.height) then
     beispiel1.Top := beispiel1.Top - 10;
     if (key = ord('S')) and (beispiel1.Top + beispiel1.Width < ClientHeight - 30then
     beispiel1.Top := beispiel1.Top + 10;
   
     if (key = vk_up) and (beispiel2.Top > irgendwasanderes.height) then
     beispiel2.Top := beispiel2.Top - 10;
     if (key = vk_down) and (beispiel2.Top + beispiel2.Width < ClientHeight - 30then
     beispiel2.Top := beispiel2.Top + 10;


Th69 - Mo 11.07.22 10:10

Das ist mit den KeyDown/Char/Up-Methoden nicht möglich, da immer nur ein Zeichen (die zuletzt gedrückte Taste) weitergeleitet wird (kannst du auch in jeder TextBox, hier im Forum oder mit Notepad u.a., nachvollziehen).
Die WinAPI bietet aber die Funktion GetAsyncKeyState [https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate] an, um den aktuellen Tastenstatus (Up oder Down) jeder einzelnen Taste zu ermitteln. Dazu solltest du dann stattdessen einen Timer verwenden, der die Tasten regelmäßig abfragt.
Zum Abfragen auf "down"-Status muß dazu dann das letzte Bit abgefragt werden:

Delphi-Quelltext
1:
if (GetAsyncKeyState(key) AND $8000) <> 0 then                    

Edited: & -> AND


jaenicke - Mo 11.07.22 12:17

user profile iconLernenochdazu hat folgendes geschrieben Zum zitierten Posting springen:
Allerdings kann ich beide shapes, wenn ich z.B w und down drücke, nicht zusammen bewegen. Nur abwechselnd. Welche Möglichkeiten habe ich, damit beides gleichzeitig geht?

[..]

Das andere Shape soll aber mit anderen Tastenkombinationen bewegt werden. Nicht mit den gleichen.
Moment, was denn nun? Zusammen bewegen oder einzeln je nach gedrückter Taste? Kannst du bitte noch einmal schreiben, wie du das meinst?

Du kannst z.B. im Parameter Shift abfragen, ob Strg, Shift, usw. gedrückt sind, wenn du z.B. mit Strg + W das andere Shape bewegen möchtest. Wenn es ganz andere Tasten sein sollen, brauchst du ja nur auf diese zu prüfen.

Aber aktuell ist mir nicht ganz klar, was du genau machen möchtest.


Gausi - Mo 11.07.22 12:28

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Aber aktuell ist mir nicht ganz klar, was du genau machen möchtest.

Ich tippe auf etwas wie einen Pong-Klon für zwei Spieler. Der erste Spieler nutzt WASD zur Steuerung, der zweite die Pfeiltasten. Dabei sollen beide Spieler gleichzeitig steuern können.

Ich würde da auch mit GetAsyncKeyState ansetzen, wie user profile iconTh69 beschrieben hat.


Lernenochdazu - Di 12.07.22 09:25

user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Aber aktuell ist mir nicht ganz klar, was du genau machen möchtest.

Ich tippe auf etwas wie einen Pong-Klon für zwei Spieler. Der erste Spieler nutzt WASD zur Steuerung, der zweite die Pfeiltasten. Dabei sollen beide Spieler gleichzeitig steuern können.

Ich würde da auch mit GetAsyncKeyState ansetzen, wie user profile iconTh69 beschrieben hat.
Richtig 🔔

user profile iconTh69 Ich hab das ganze mal ausprobiert, ich kann nun auch beide Tasten zusammen bewegen! Danke dafür schonmal. Allerdings brauch es sehr lange bis die beiden Shapes ihre Position updaten, was kann ich dagegen tun? Und wofür steht das & $8000? Wird bei mir nicht gefunden.

Bisherige Lösung, in einem Timer:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
     if ((GetAsyncKeyState(vk_up) <> 0and (beispiel.Top > beispiel.height)) then
        beispiel.Top := beispiel.Top - 10;
     if ((GetAsyncKeyState(vk_down) <> 0and (beispiel.Top + beispiel.Width < ClientHeight)) then
        beispiel.Top := beispiel.Top + 10;

     if ((GetAsyncKeyState(Ord('W')) <>0and (beispiel.Top > beispiel.height)) then
        beispiel.Top := beispiel.Top - 10;
     if ((GetAsyncKeyState(Ord('S')) <> 0and (beispiel.Top + beispiel.Width < ClientHeight)) then
        beispiel.Top := beispiel.Top + 10;


Gausi - Di 12.07.22 09:49

user profile iconLernenochdazu hat folgendes geschrieben Zum zitierten Posting springen:
Allerdings brauch es sehr lange bis die beiden Shapes ihre Position updaten, was kann ich dagegen tun? Und wofür steht das & $8000? Wird bei mir nicht gefunden.

Probier mal

Delphi-Quelltext
1:
if (GetAsyncKeyState(key) AND $8000) <> 0 then                    

Dabei wird ein bestimmtes Bit des Rückgabewertes von GetAsyncKeyState überprüft. Der binäre UND-Operator ist in Delphi AND, nicht &

Wie lange dauert es denn, bis sich die Shapes updaten? Hast du das Timer-Intervall vom Standard 1000ms auf einen kleineren Wert gesetzt? 25-50ms würde ich hier ansetzen - zu kleine Intervalle bringen nämlich auch nichts.


Th69 - Di 12.07.22 09:57

Genau, ich hatte mich mit C++ bzw. C# vertan.

Zum Neuzeichnen der Shapes (nach der Positionsveränderung) Invalidate [https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Controls.TControl.Invalidate] oder Refresh [https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Controls.TControl.Refresh] aufrufen.