Blog

All Blog Posts  |  Next Post  |  Previous Post

VCL Grid goodies

Friday, February 19, 2021

TMS Software Delphi  Components

A little known and little used but at the same time very powerful feature is the use of HTML controls in TAdvStringGrid cells. HTML controls are the concept of specifying controls for cells via HTML tags in the HTML assigned to a grid cell. It is the grid HTML  engine that is then responsible for rendering the controls and for handling the interacting with these controls.

Among the supported controls are : checkbox, radiobutton, button, edit, combobox.

While the grid alternatively has functions to add a checkbox, button, radiobutton to a cell via grid.AddCheckBox(), grid.AddButton(), grid.AddRadioButton(), using HTML controls means you can add as many of these controls you want, in the order you want and mixed with text and images. 

Performance and resources

You might wonder why introducing this concept when you could add a TPanel instance to a cell with grid.CellControls[Col,Row] and add any control you want to the panel to have these in a grid cell. While this is a perfectly possible approach, this quickly turns into a very bad idea when you would want to fill hundreds or thousands of cells in the grid. Note that for a grid of only 100x100 columns/rows, there are already 10.000 cells. When you would add for each cell a TPanel with on the TPanel a TCheckBox, TEdit and TButton, this means you would ask Windows to allocate 4 window handles for each of these controls per cell. For a 100x100 grid, this is creating 40.000 window handles. This is absolutely not a good idea to waste precious Windows resources & performance for!

Resource friendly HTML controls

When adding HTML controls to a cell, this HTML control only exists in the cell string value and is rendered when the cell needs to be rendered only. It is rendering using drawing, no real Windows controls are involved. In a 100x100 columns/rows grid, it is only the visible cells that well be rendered, so typically far less than 10.000 cells. Also when the user interacts with a checkbox, radiobutton or regular HTML control button, there is never a real Windows control involved. All is rendered by the grid. It is only when the user starts editing in a HTML edit or combobox control that just during editing time, a real Windows control is involved. That means, the grid  will internally create a TEdit or TComboBox control, position it in the cell, allow the editing and will remove the control again after editing.

You can see that with this architecture, whether you add 10.000, 50.000 or even more HTML controls does not really matter for performance or resource usage. Maximum one control at a time will be live and used.

Using HTML controls

Using HTML controls is simple. These are represented in the cell HTML as tags of the type <CONTROL> and this tag had the attributes:

  • TYPE: sets the type of the control. This can be EDIT, CHECK, RADIO, BUTTON, COMBO
  • WIDTH: sets the width in pixels for the control
  • VALUE: sets the value of the control 
  • ID: a unique control identifier that can be used to programmatically get & set its value

To get or set a control value, the grid has the property

grid.ControlValues[Col,Row: integer; ID: string): string;

When the user interacts with any of the HTML controls in the cell, the grid can notify with the following events:

grid.OnControlClick       : event triggered when a control is clicked, returns the ID of the control

grid.OnControlComboList   : event triggered to query values for a HTML control combobox when it is about to be edited

grid.OnControlComboSelect : event triggered when the user has selected a value in a HTML combobox control

grid.OnControlEditDone    : event triggered when the editing in a HTML edit control stopped by user leaving focus
 


Putting it together

Here is a code snippet that initializes a default grid with 2 cells that feature HTML controls:

procedure TForm1.FormCreate(Sender: TObject);
var
  UserName: array[0..128] of char;
  szUserName: cardinal;
begin
  szUserName := 128;
  GetUserName(UserName, szUserName);

  AdvStringGrid1.ColWidths[1] := 192;
  AdvStringGrid1.RowHeights[1] := 72;
  AdvStringGrid1.RowHeights[2] := 72;

  // if we want the HTML controls in the cell to be enabled for editing, editing needs to be enabled at grid level
  AdvStringGrid1.Options := AdvStringGrid1.Options + [goEditing];

  // adds a checkbox and button HTML control to cell 1,1
  AdvStringGrid1.Cells[1,1] := '<CONTROL TYPE="CHECK" WIDTH="24" ID="CHK"> <IMG SRC="IDX:0"> Microphone <BR><BR><CONTROL TYPE="BUTTON" WIDTH="80" ID="BTN1" VALUE="Connect">';

  // adds an edit control and button HTML control to cell 1,2
  AdvStringGrid1.Cells[1,2] := 'Username: <CONTROL TYPE="EDIT" WIDTH="128" ID="USER"> <BR><CONTROL TYPE="BUTTON" WIDTH="80" ID="BTN2" VALUE="Login">';

  // initializes the value of the HTML edit control in cell 1,2 to the Windows username
  AdvStringGrid1.ControlValues[1,2,'USER'] := UserName;
end;

Now, we can react to events triggered from the HTML cell controls by implementing the grid.OnControlClick event and check for the unique ID of the HTML control that triggered the event:

procedure TForm1.AdvStringGrid1ControlClick(Sender: TObject; ARow,
  ACol: Integer; CtrlID, CtrlType, CtrlVal: string);
var
  v: string;
begin
  // check of button in cell 1,1 was clicked
  if CtrlID = 'BTN1' then
  begin
    // get value of the HTML check control in cell 1,1. 
    // HTML check value returns TRUE when checked or empty when not checked
    v := AdvStringGrid1.ControlValues[1,1,'CHK'];
    if v = 'TRUE' then
      ShowMessage('Connect with microphone')
    else
      ShowMessage('Connect without microphone');
  end;

  // check of button in cell 1,2 was clicked
  if CtrlID = 'BTN2' then
  begin
    // get value of the HTML edit control in cell 1,2 
    v := AdvStringGrid1.ControlValues[1,2,'USER'];
    ShowMessage('Login for '+ v);
  end;
end;

The result when running a VCL application with TAdvStringGrid and the cell controls is:

TMS Software Delphi  Components

Summary

TAdvStringGrid is all about flexibility and packed with features. HTML controls in cells can be that specific feature you are looking for to give your users a performance & resource friendly but better experience dealing with interaction in cells.
Note that besides HTML controls, the mini-HTML rendering engine in TAdvStringGrid can do much more other things to nicely format and visually fine-tune appearance of data in cells. For details about the capabilities of this small but fast mini-HTML rendering engine, check this resource. Note that these mini-HTML capabilities are also available in many more mini-HTML enabled VCL controls in the TMS VCL UI Pack.

More #GRIDGOODIES ?

Today's #GRIDGOODIES article was requested by a user of the TMS VCL UI Pack's TAdvStringGrid. If you also have suggestions or ideas to cover a maybe lesser known feature in the grid, let us know in the comments or by email!



Bruno Fierens




This blog post has not received any comments yet.



Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post