user1769184
user1769184

Reputation: 1621

Sender as TObject for Case ... of with Delphi

would like to use a Sender as TObject as a selection criteria for my case ... statement

procedure TForm.ShowGUI (Sender: TObject);
begin
  case sender of
      ToolButton1: begin
          do_something;         
        end;

      ToolButton2: begin
          /// 
        end;

      ToolButton3: begin
          do_stufff_here; 
        end;

      ToolButton3: begin 
          /// 
        end;

      else ;

  end;
end;

An trick to make the sender an ordinal type as requested by the case statement ?

Upvotes: 3

Views: 5445

Answers (2)

David Heffernan
David Heffernan

Reputation: 612993

Consider adding a bit of runtime support to associate an enumeration with your controls.

First create an enumerated type:

type
  TControlID = (cidAlignTextLeft, cidAlignTextRight, ....);

Then add a dictionary to your form:

FControlIDs: TDictionary<TControl, TControlID>;

Then in the form's constructor create and populate the dictionary:

FControlIDs := TDictionary<TControl, TControlID>.Create;
FControlIDs.Add(tbAlignTextLeft, cidAlignTextLeft);
FControlIDs.Add(tbAlignTextRight, cidAlignTextRight);
....

This section of code should be placed in a separate local helper function rather than inline in your form's constructor.

Now you can write your case statement:

case FControlIDs[Sender as TControl] of
cidAlignTextLeft:
  ....
cidAlignTextRight:
  ....

Upvotes: 6

Cosmin Prund
Cosmin Prund

Reputation: 25678

You can easily convert the Sender to an ordinal by converting it to an integer (example: NativeUInt(Sender) - but that will do you no good because the case statement expects constant expressions for the "branches", and ToolButton1..ToolButton3 aren't constants, they're variables.

You could for example do a case on a property of the buttons; For example, give each ToolButton a Tag property that's meaningful for it. Then you could do something like this:

case (Sender as TToolButton).Tag of
  1: ; // ToolButton1 was pressed
  2: ; // ToolButton2 was pressed        
end;

As suggested by David: Unless the control you're using has a property that directly relates to it's function (very unlikely), then a simple chained if statement might be easier to read. The Tag property as in my first suggestion would need to be specifically configured, and it's just an other way to introduce errors. Example: maybe you copy-paste a button but forget to change it's Tag, you've now got two buttons with the same Tag.

First of all, you should rename all the components you're using from code, give them proper names. Then you could write something like this:

if (Sender = tbAlignTextLeft) then
  begin
     // The tool-button for left text alignment was pressed
  end
else if (Sender = tbAlignTextCenter) then
  begin
    // Center-alignment button was pressed
  end
else
  begin
    // This would be the default action. If it were me, I'd raise an exception here.
  end

Upvotes: 10

Related Questions