Recent

Author Topic: "case style" statements for elements of a set variable?  (Read 2359 times)

741

  • New Member
  • *
  • Posts: 27
"case style" statements for elements of a set variable?
« on: August 02, 2025, 12:58:58 pm »
This is what I'm trying to do.
Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.pbxGridMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  2. begin
  3.   case Shift of  //Invalid code, but shows what I'd like to achieve
  4.      ssLeft: sbrImagZ.Panels[1].Text := 'Left Down';
  5.      ssRight: sbrImagZ.Panels[1].Text := 'Right Down';
  6. ...//etc
  7.   end;
I can see it is not valid because the set 'Shift' may contain more than one element. Would I have to use
Code: [Select]
if ssLeft in Shift then //...Maybe theere is a neater way?


Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12429
  • Debugger - SynEdit - and more
    • wiki
Re: "case style" statements for elements of a set variable?
« Reply #1 on: August 02, 2025, 02:11:54 pm »
The short answer is: You can't use case. You have to use the "if" statements.



The long answer is, if you want to go on a tricky, slippery path and use some hacked together code .... You can get case do to the job. But as you said "there can be multiple enums set". The "case" will see each combination as a different option.

I do _ NOT _ recommend the below. Do not use it.
The below is for fun of hacking the code, not for use in any app.

It will probably break, if you use any options that change the size of sets.
It also depends on the CPU (big endian vs little endian).

Code: Pascal  [Select][+][-]
  1. // Example of really bad code
  2. var
  3.   c: TShiftState;
  4. begin
  5.   c := [ssRight];
  6.   // Example of really bad code
  7.   case cardinal(c) of
  8.     1 << (ord(ssLeft))  : writeln('left');
  9.     1 << (ord(ssRight)) : writeln('right');
  10.     (1 << (ord(ssLeft))) or
  11.     (1 << (ord(ssRight))) : writeln('both');
  12.     otherwise
  13.       writeln('left/right may still be set, but combined with other enums in the set');
  14.   end;
  15. end;
  16.  
« Last Edit: August 02, 2025, 02:18:16 pm by Martin_fr »

cdbc

  • Hero Member
  • *****
  • Posts: 2818
    • http://www.cdbc.dk
Re: "case style" statements for elements of a set variable?
« Reply #2 on: August 02, 2025, 02:15:50 pm »
Hi
There is an old trick, from before one could put strings in a 'case' statement...
In unit 'StrUtils' look for this:
Code: Pascal  [Select][+][-]
  1. function AnsiIndexStr(const AText: AnsiString; const AValues: array of AnsiString): Integer;
  2. begin
  3.   for result:=low(AValues) to High(Avalues) do
  4.      if (avalues[result]=AText) Then
  5.        exit;                                    // make sure it is the first val.
  6.   result:=-1;
  7. end;
Normally you'd use it like this:
Code: Pascal  [Select][+][-]
  1. ...
  2.   case AnsiIndexStr('Two',['One','Two','Three','Four']) of
  3.     0: showmessage('One');
  4.     1: showmessage('Two');
  5.     ... etc
  6.   end;
  7. ...
MeThinks it would be a small, short task to create a function for TShiftState  ;D
Then you could use 'case' for that too  8)
eta: !!! Beware: the above function ONLY returns the first occurrence -- Well in hindsight it's probably a shijty solution, forget 'bout it...
Regards Benny
« Last Edit: August 02, 2025, 02:20:50 pm by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

jamie

  • Hero Member
  • *****
  • Posts: 7773
Re: "case style" statements for elements of a set variable?
« Reply #3 on: August 02, 2025, 03:33:58 pm »
To explain it better, TShiftState is a SET with means it represents multiple set values into one.

A Case only works with single values like an ENUMERATOR where the object holding the definition holds only one item per case. In this situation, the SET can hold multiple states as indicated.

 So using the IN operator is normally the chosen way.

Jamie
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7773
Re: "case style" statements for elements of a set variable?
« Reply #4 on: August 02, 2025, 03:59:09 pm »
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  2.   Y: Integer);
  3. begin
  4.   Case LongBool(LongInt(Shift) and ((Ord(ssCtrl)+1) Shl Ord(ssCtrl))) Of
  5.    true:Caption := DateTimeTostr(Now);
  6.    False:Caption := 'Control not down';
  7.   End;
  8. end;                                
  9.  

To give you a perspective of what it would be like to use a case statement for just one item in the set.

Jamie
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7773
Re: "case style" statements for elements of a set variable?
« Reply #5 on: August 02, 2025, 04:05:14 pm »
But

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  2.   Y: Integer);
  3.  Var
  4.    I :TShiftStateEnum;
  5.    S:String;
  6. begin
  7.   S:= 'Nothing pressed';
  8.   For I in Shift do
  9.    Case I of
  10.      ssShift :S := 'Shift';
  11.      ssAlt   :S := 'Alt Key';
  12.      ssCtrl  :S:= 'Control Key';
  13.    end;
  14.   Caption := S;
  15. end;                                      
  16.  
  17.  
jamie :D
The only true wisdom is knowing you know nothing

d2010

  • Sr. Member
  • ****
  • Posts: 264
Re: "case style" statements for elements of a set variable?
« Reply #6 on: August 02, 2025, 05:24:57 pm »
But

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  2. end;                                      
  3.  
jamie :D
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);
  2.  Var
  3.    I :TShiftStateEnum;
  4.    S:String;
  5. begin
  6.   S:='';
  7.   For I in Shift do
  8.    Case I of
  9.      ssShift :S := s+'Shift+';
  10.      ssAlt   :S := s+'Alt Key+';
  11.      ssCtrl  :S:= s+'Control Key+';
  12.    end;
  13.   if length(s)<03 then caption:='Nothing pressed ! Please you try again<<case style" statements for elements of a set variable?'   else
  14.      Caption := copy(S,1,length(s)-0001);
  15. end;                                      
  16.  
« Last Edit: August 02, 2025, 05:26:28 pm by d2010 »

741

  • New Member
  • *
  • Posts: 27
Re: "case style" statements for elements of a set variable?
« Reply #7 on: August 02, 2025, 10:01:45 pm »
Glad I asked, lots of interesting replies and looks like a solution too :)
Thanks one & all.

ASerge

  • Hero Member
  • *****
  • Posts: 2499
Re: "case style" statements for elements of a set variable?
« Reply #8 on: August 03, 2025, 08:12:38 pm »
Code: Pascal  [Select][+][-]
  1. uses TypInfo;
  2.  
  3. procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  4. var
  5.   P: PTypeInfo;
  6. begin
  7.   P := TypeInfo(Shift);
  8.   Caption := SetToString(P, @Shift, True);
  9. end;

jamie

  • Hero Member
  • *****
  • Posts: 7773
Re: "case style" statements for elements of a set variable?
« Reply #9 on: August 03, 2025, 08:36:33 pm »
Code: Pascal  [Select][+][-]
  1. uses TypInfo;
  2.  
  3. procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  4. var
  5.   P: PTypeInfo;
  6. begin
  7.   P := TypeInfo(Shift);
  8.   Caption := SetToString(P, @Shift, True);
  9. end;

You are going to the Dark Side with all this high-level STUFF!!!!  ::)
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018