Name von Aufzähltypen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

PascalDragon hat geschrieben: So 26. Jan 2025, 16:23
Jorg3000 hat geschrieben: Fr 24. Jan 2025, 07:21 Im Plus-Paket wird mir bei gleicher Fragestellung eine andere, ebenfalls funktionierende(!) Lösung ausgespuckt:

Code: Alles auswählen

  uses TypInfo;
  var x: (blau, gelb, rot);
  x := gelb;
  s := GetEnumName( TypeInfo(x), Ord(x) );
  ShowMessage(s); // Writeln(s);  
Ich kannte bisher keine der Lösungsmöglichkeiten, weder über GetEnumName() noch über Str() - also gut, dass es dieses Forum gibt. :)
Bitte beachte, dass die Variante mit GetEnumName nicht geht, wenn das Enum Lücken hat, da es dann keine gültige Typinformation gibt und daher TypeInfo(<Bezeichner>) nicht kompiliert:

Code: Alles auswählen

program tenum;

{$mode objfpc}
{$scopedenums on}

uses
  TypInfo;

type
  TTestEnum = (a, b, c);
  TTestEnum2 = (a = 1, b, c);

var
  e: TTestEnum;
  e2: TTestEnum2;
  s: String;
begin
  e := TTestEnum.b;
  e2 := TTestEnum2.b;
  Str(e, s);
  Writeln(s);
  Str(e2, s);
  Writeln(s);
  s := GetEnumName(TypeInfo(e), Ord(e));
  Writeln(s);
  // error: No type info available for this type
  {s := GetEnumName(TypeInfo(e2), Ord(e2));
  Writeln(s);}
end.

Das habe ich jetzt mal versucht anzuwenden - ich bekomme es nicht hin ...

Was mache ich in der

Code: Alles auswählen

procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  aStr: string;
  aEnum: tShiftState;
begin
  Label2.Caption := '';
  Label3.Caption := '';
  Label4.Caption := '';
  Label5.Caption := '';

  //aEnum := tShiftState.ssShift;
  //aEnum := ssShift;
  //aStr := GetEnumName(TypeInfo(tShiftState.aEnum), Shift);  

im auskommentierten Bereich falsch?

ShowUsedKey.7z
(149.79 KiB) 25-mal heruntergeladen
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

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

Re: Name von Aufzähltypen

Beitrag von theo »

TShiftState ist kein Enum sondern ein Set:

Code: Alles auswählen

  TShiftStateEnum = (ssShift, ssAlt, ssCtrl,
    ssLeft, ssRight, ssMiddle, ssDouble,
    // Extra additions
    ssMeta, ssSuper, ssHyper, ssAltGr, ssCaps, ssNum,
    ssScroll,ssTriple,ssQuad,ssExtra1,ssExtra2);

  TShiftState = set of TShiftStateEnum;     
Auch in deinem Code im Zip ist das eigentlich nicht ganz richtig.
Statt
if Shift = [ssShift] then..
..wäre so besser:
if ssShift in Shift then..

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

theo hat geschrieben: Fr 14. Feb 2025, 11:05 TShiftState ist kein Enum sondern ein Set:

Code: Alles auswählen

  TShiftStateEnum = (ssShift, ssAlt, ssCtrl,
    ssLeft, ssRight, ssMiddle, ssDouble,
    // Extra additions
    ssMeta, ssSuper, ssHyper, ssAltGr, ssCaps, ssNum,
    ssScroll,ssTriple,ssQuad,ssExtra1,ssExtra2);

  TShiftState = set of TShiftStateEnum;     
Auch in deinem Code im Zip ist das eigentlich nicht ganz richtig.
Statt
if Shift = [ssShift] then..
..wäre so besser:
if ssShift in Shift then..

Ok, Danke für den Tipp.

Da ist dann aber auch mein eigentliches Problem nicht gelöst: Wenn ich die Abfrage über if then mache, dann wird mein Programm auch dann reagieren, wenn die User z. B. Ctrl und Shift drücken. Wird Ctrl zuerst gedrückt, dann wird da schon was passieren und dann nochmal was, wenn Shift dazukommt.

Daher möchte ich mit case of arbeiten ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

theo hat geschrieben: Fr 14. Feb 2025, 11:05 TShiftState ist kein Enum sondern ein Set:

Code: Alles auswählen

  TShiftStateEnum = (ssShift, ssAlt, ssCtrl,
    ssLeft, ssRight, ssMiddle, ssDouble,
    // Extra additions
    ssMeta, ssSuper, ssHyper, ssAltGr, ssCaps, ssNum,
    ssScroll,ssTriple,ssQuad,ssExtra1,ssExtra2);

  TShiftState = set of TShiftStateEnum;     
Auch in deinem Code im Zip ist das eigentlich nicht ganz richtig.
Statt
if Shift = [ssShift] then..
..wäre so besser:
if ssShift in Shift then..
Hab' Deine Schreibweise ausprobiert - geht nicht, wenn ich das Drücken mehrerer Tasten erfassen möchte - bei meiner Schreibweise funktioniert das ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

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

Re: Name von Aufzähltypen

Beitrag von theo »

Niesi hat geschrieben: Fr 14. Feb 2025, 11:40 Hab' Deine Schreibweise ausprobiert - geht nicht, wenn ich das Drücken mehrerer Tasten erfassen möchte - bei meiner Schreibweise funktioniert das ...
Verstehe nicht, das ergibt so keinen Sinn. Die Variante mit "in" ist ja weniger restriktiv.
Teste doch mal, was grundsätzlich passiert.
Beim ersten Drücken von Shift, ist ssShift gar nicht im Set drin, nur im Key ist die Shifttaste drin.

Testcode:

Code: Alles auswählen

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState );
begin
 Memo1.Lines.Add(Key.ToString);
 if ssShift in Shift then Memo1.Lines.Add('ssShift') else Memo1.Lines.Add('kein ssShift');
 if ssCtrl in Shift then Memo1.Lines.Add('ssCtrl') else Memo1.Lines.Add('kein ssCtrl');
 if Shift = [ssShift] then Memo1.Lines.Add('= ssShift') else Memo1.Lines.Add('kein = ssShift');
end;   
Das ergibt bei mir beim Drücken von Shift+Ctrl+Buchstabe:

16 (Anm: VK_SHIFT)
kein ssShift
kein ssCtrl
kein = ssShift
17 (Anm: VK_CONTROL)
ssShift
kein ssCtrl
= ssShift
71
ssShift
ssCtrl
kein = ssShift

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1639
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Name von Aufzähltypen

Beitrag von fliegermichl »

Wieso das denn?

Code: Alles auswählen

  if (Shift = [ssCtrl, ssShift]) then ShowMessage('Jetzt');
funktioniert doch einwandfrei.

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

Re: Name von Aufzähltypen

Beitrag von theo »

fliegermichl hat geschrieben: Fr 14. Feb 2025, 11:54 Wieso das denn?

Code: Alles auswählen

  if (Shift = [ssCtrl, ssShift]) then ShowMessage('Jetzt');
funktioniert doch einwandfrei.
Ja, wenn du nur wissen willst, ob gleichzeitig Ctrl und Shift gedrückt sind.
In allen anderen Fällen reagiert das nicht.
Kommt halt drauf an, was man braucht.

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

theo hat geschrieben: Fr 14. Feb 2025, 11:57
fliegermichl hat geschrieben: Fr 14. Feb 2025, 11:54 Wieso das denn?

Code: Alles auswählen

  if (Shift = [ssCtrl, ssShift]) then ShowMessage('Jetzt');
funktioniert doch einwandfrei.
Ja, wenn du nur wissen willst, ob gleichzeitig Ctrl und Shift gedrückt sind.
In allen anderen Fällen reagiert das nicht.
Kommt halt drauf an, was man braucht.
Wieso ist das mit Klammern und "=" bei mehreren Tasten ok, bei einzelnen Tasten aber nicht?????

Jedenfalls: So geht es mit "in":

Code: Alles auswählen

  if ssShift  in Shift then Label5.Caption := 'OnKeyDown: Shift = ssShift';
  if ssAlt    in Shift then Label5.Caption := 'OnKeyDown: Shift = ssAlt';
  if ssCtrl   in Shift then Label5.Caption := 'OnKeyDown: Shift = ssCtrl';
  if (ssCtrl  in shift) and (ssAlt   in Shift) then Label5.Caption := 'OnkeyDown: Shift = ssCtrl + ssAlt';
  if (ssCtrl  in Shift) and (ssShift in Shift) then Label5.Caption := 'OnkeyDown: Shift = ssCtrl + ssShift';
  if (ssShift in Shift) and (ssAlt   in Shift) then Label5.Caption := 'OnkeyDown: Shift = ssShift + ssAlt';
  if (ssShift in Shift) and (ssAlt in Shift) and (ssCtrl in Shift) then Label5.Caption := 'OnkeyDown: Shift = ssShift + ssAlt + ssCtrl';    
  
Aber so bekomme ich auch nicht die gewünschte Handhabung der Ereignisse hin ...

Nur "Shift" gedrückt:
Auswahl_022.png
Auswahl_022.png (27.03 KiB) 4190 mal betrachtet

Jetzt "Ctrl" mitgedrückt:
Auswahl_023.png
Auswahl_023.png (27.31 KiB) 4190 mal betrachtet

Und nun nocht "Alt" dazu:
Auswahl_024.png
Auswahl_024.png (27.85 KiB) 4190 mal betrachtet


Es werden nacheinander die Reaktionen auf "Shift", "Shift + Ctrl" und "Shift + Ctrl + Alt" abgearbeitet. Die User wollen aber nur die Reaktion auf "Shift + Ctrl + Alt" erreichen.

Das kann doch nicht richtig sein ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

Hier noch der geänderte Quellcode:
ShowUsedKey~05.7z
(150 KiB) 52-mal heruntergeladen
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

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

Re: Name von Aufzähltypen

Beitrag von theo »

@Niesi: Hast du mein Beispiel oben ausprobiert?
Das müsste doch die Fragen klären.
Man muss natürlich nicht "in" verwenden. Nur wenn man wissen will, ob die Taste in irgend einer Kombination gedrückt ist.
Wenn man nur bestimmte Kombinationen prüfen will, ist z.B. = [ssCtrl, ssShift] einfacher.
In der Schule hiess das Ganze glaube ich "Mengenlehre" (x∈M vs M=N). :wink:

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

theo hat geschrieben: Fr 14. Feb 2025, 12:36 @Niesi: Hast du mein Beispiel oben ausprobiert?
Das müsste doch die Fragen klären.
Man muss natürlich nicht "in" verwenden. Nur wenn man wissen will, ob die Taste in irgend einer Kombination gedrückt ist.
Wenn man nur bestimmte Kombinationen prüfen will, ist z.B. = [ssCtrl, ssShift] einfacher.
In der Schule hiess das Ganze glaube ich "Mengenlehre". :wink:
Klar doch, ich mache das jetzt so:

Code: Alles auswählen

  if Shift = [ssShift]  then Label5.Caption := 'OnKeyDown: Shift = ssShift';
  if Shift = [ssAlt]    then Label5.Caption := 'OnKeyDown: Shift = ssAlt';
  if Shift = [ssCtrl]   then Label5.Caption := 'OnKeyDown: Shift = ssCtrl';
  if Shift = [ssCtrl, ssAlt]   then Label5.Caption := 'OnkeyDown: Shift = ssCtrl + ssAlt';
  if Shift = [ssCtrl, ssShift] then Label5.Caption := 'OnkeyDown: Shift = ssCtrl + ssShift';
  if Shift = [ssShift, ssAlt]  then Label5.Caption := 'OnkeyDown: Shift = ssShift + ssAlt';
  if Shift = [ssShift, ssAlt, ssCtrl] then Label5.Caption := 'OnkeyDown: Shift = ssShift + ssAlt + ssCtrl';  
Das ist dann für alle gleich, auch die, die nur eine Taste haben.

Allerdings muss ich zugeben, dass mein Wunsch nach Unterscheidung der Tastenkombinationen Quatsch ist. Auf das Drücken von nur "Shift", nur "Ctrl" oder nur "ALT" dürfte gar keine Reaktion erfolgen - es muss ja immer mindestens eine weitere Taste gedrückt werden. Ist also dahingehend erledigt.

Bedauerlich finde ich, dass dieses blöde Set "tShiftState" nicht mit "case of" gehandhabt werden kann ...

ShowUsedKey~04.7z
(149.82 KiB) 37-mal heruntergeladen
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

PascalDragon
Beiträge: 945
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Name von Aufzähltypen

Beitrag von PascalDragon »

Niesi hat geschrieben: Fr 14. Feb 2025, 11:31
theo hat geschrieben: Fr 14. Feb 2025, 11:05 TShiftState ist kein Enum sondern ein Set:

Code: Alles auswählen

  TShiftStateEnum = (ssShift, ssAlt, ssCtrl,
    ssLeft, ssRight, ssMiddle, ssDouble,
    // Extra additions
    ssMeta, ssSuper, ssHyper, ssAltGr, ssCaps, ssNum,
    ssScroll,ssTriple,ssQuad,ssExtra1,ssExtra2);

  TShiftState = set of TShiftStateEnum;     
Auch in deinem Code im Zip ist das eigentlich nicht ganz richtig.
Statt
if Shift = [ssShift] then..
..wäre so besser:
if ssShift in Shift then..

Ok, Danke für den Tipp.

Da ist dann aber auch mein eigentliches Problem nicht gelöst: Wenn ich die Abfrage über if then mache, dann wird mein Programm auch dann reagieren, wenn die User z. B. Ctrl und Shift drücken. Wird Ctrl zuerst gedrückt, dann wird da schon was passieren und dann nochmal was, wenn Shift dazukommt.

Daher möchte ich mit case of arbeiten ...
case geht für Sets einfach nicht.

Was du in deinem Fall machen kannst: definiere eine Konstante mit all Elementen aus TShiftStateEnum, die du entweder beachten oder ausschließen möchtest. Und dann prüfst du, dass die Schnittmenge nur das enthält, was du möchtest:

Code: Alles auswählen

const
  HandledState = [ssCtrl, ssAlt, ssShift];
begin
  if Shift * HandledState = [ssShift] then
    ...
end;
FPC Compiler Entwickler

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 580
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon, Laz 3.9 Fpc 3.2.3 und allerlei mit FpcUpDeLuxe
Kontaktdaten:

Re: Name von Aufzähltypen

Beitrag von Niesi »

[quote=PascalDragon post_id=148206 t

...

Was du in deinem Fall machen kannst: definiere eine Konstante mit all Elementen aus TShiftStateEnum, die du entweder beachten oder ausschließen möchtest. Und dann prüfst du, dass die Schnittmenge nur das enthält, was du möchtest:

Code: Alles auswählen

const
  HandledState = [ssCtrl, ssAlt, ssShift];
begin
  if Shift * HandledState = [ssShift] then
    ...
end;
[/quote]

Danke, heute hab ich es besser verstanden. Mein Sohn hat's mir erklärt ... :lol:

Ich war der irrigen Annahme, dass das in tShiftState Enums sind - wie Du schreibst: Es ist ein Set ...

Tja, wieder was gelernt - Danke an alle für die Geduld ... :D
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Antworten