Looking at contents of your EWB Form

by Erick Engelke
August 27, 2024

Sometimes you would like to programatically access the various controls on your page.

For example, here is a page which generates a summary of the controls, their names, types, position (Left,Top), and contents. The list is generated when you press the clickme. That calls ListThem, a relatively simple function defined below.

post33a

procedure TForm1.ListThem;
var
   i : integer;
   c : TControl;
   s : string;
   xy : string;
begin
   multilineedit1.Lines.Clear;
   for i := 0 to controlCount - 1 do begin
      c := controls[i];

      // default to no data contents
      s := '';

      // read the data contents Caption or Text
      if c is TButton then s := TButton(c).Caption;
      if c is TLabel then s := TLabel(c).Caption;
      if c is TEditComboBox then s := TEditComboBox(c).Text;
      if c is TEdit then s := TEdit(c).Text;

      // get the X,Y location of Left, Top for the control
      xy := IntToStr( c.left ) + ', ' + IntToStr( c.top );

      multilineedit1.Lines.Add('Control: ' + c.name + ' type: ' + c.classname + ' position: '+xy+ ' contents: ' + s);

   end;
end;

procedure TForm1.Label1Click(Sender: TObject);
begin
  listthem;
end;

Note that the visual controls are all descendants of TControl or descendants of TControl’s descendants, and every form (and every container, like TGroupBox and TPanel) have a list of _sub_controls you can iterate through.

The Pascal word is lets you compare to whether the class is of a specific type. So we handle each of the cases we expect with an is statement.

Note: even though TButton and TLabel both have Captions, we cannot share code to read the caption because the class is different, and internally they point to different member fields. We can only share code to read common things found through the same parent classes, like Top, Left, Name, ClassName, etc.

If you use a container class, like TBasicPanel, TGroupPanel, TScollPanel, TPain, TNotebook, etc. each will contain a list of controls. So to see all the _sub_controles you will typically use recursion.

procedure TForm1.ListThemRecursive( master: TControl );
var
   i : integer;
   c : TControl;
   s : string;
   xy : string;
begin
   for i := 0 to master.controlCount - 1 do begin
      c := master.controls[i];

      // default to no data contents
      s := '';

      // read the data contents Caption or Text
      if c is TButton then s := TButton(c).Caption;
      if c is TLabel then s := TLabel(c).Caption;
      if c is TEditComboBox then s := TEditComboBox(c).Text;
      if c is TEdit then s := TEdit(c).Text;

      // get the X,Y location of Left, Top for the control
      xy := IntToStr( c.left ) + ', ' + IntToStr( c.top );

      multilineedit1.Lines.Add('Parent: '+master.name + ' Control # '+inttostr(i)+': ' + c.name + ' type: ' + c.classname + ' position: '+xy+ ' contents: ' + s);

      // recurse down
      ListThemRecursive( c );
   end;
   // insert a blank line after each recusion with more than 0 sub controls
   if i > 0 then multilineedit1.Lines.Add('');
end;

procedure TForm1.MultiLineEdit1Click(Sender: TObject);
begin
   MultiLineEdit1.Lines.Clear;
   ListThemRecursive( form1 );
end;

This is an example of recursive searching with two TBasicPanels (one is light red, the other pink), and sub controls

post33b

Notice that the EditCombox Box has a sub control of TListComboBox built-in. We didn’t add that, that’s part of EWB.

Using Tag field

All TControls have a Tag field which can hold a number. Sometimes you will enumerate all TControls, then make a determination on the Tag you set earlier, or on a KeyStroke event (ie. changed field).

Sample Uses: Validation

Suppose you want to ensure someone has filled out all the TEdits and other controls in a complex form to validate that there is something entered. Simply enumerate as above, then pop up an error message saying to enter all data.

You can even hover a TBalloonLabel slightly over the missing field, because you know the Left and Top positions relative to the owning container, and use that to guide the user to the right field.

I do that in several programs.

Summary

Once you know how to programatically enumerate (ie. list) the controls, you have all new options available to you to simplify coding while improving the user experience.