Home Articles  
Events
Support
About Us
Search
 
 
 
 
 
 

Changing Cell Font Properties in the FireMonkey TStringGrid

Updated for RAD Studio XE4 and XE5

After one of my CodeRage presentations on creating FireMonkey Controls, I received the following question via email:

How do you change the font size of a TStringGrid in FireMonkey?

This is a very good question. Sounds simple enough, but it turns out that it is anything but simple. However, before diving into what is needed to accomplish the above, we first need to setup our TStringGrid which is a bit different in FMX. We'll start by creating a new FireMonkey HD application and drop a TStringGrid on the form. Next, we need to add one or more columns to the grid. To do this, right-click on the TStringGrid and select "Add Item" from the context menu. This will create a new TStringColumn to the grid. With one or more TStringColumn instances created, we can use the Cells property at runtime to populate the grid. For example,

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.Cells[ 0, 0 ] := 'Cell00';
  StringGrid1.Cells[ 1, 0 ] := 'Cell10';

  StringGrid1.Cells[ 0, 1 ] := 'Cell01';
  StringGrid1.Cells[ 1, 1 ] := 'Cell11';
end;

Getting back to the original question of modifying the font size of the grid cells. I first tried to modify the style using the Style Designer, but there is no style associated with the cells at the grid level. I then tried the TStringColumn level, and there is no style at all for that. When I looked at the source code I saw that the TStringColumn manages a list of CellControls, which for the TStringGrid is a list of TTextCell instances. And TTextCell is a direct descendant of TEdit.

Well, changing the text size is pretty straight forward for a TEdit, you just modify the Font.Size property. However, this got me thinking about what if I wanted to modify the text color of the TEdit and not just the Font.Size or Font.FamilyName. This used to be a bit of a challenge, but fortunately, the FontColor property was added to the TEdit class that makes changing the font color easy. However, when we change Font.Size or FontColor, we need to make sure that we remove the ssSize and ssFontColor elements from the TEdit.StyledSettings property. If we do not, then the changes will have no effect.

This is all well and good, but going back to the StringGrid, there is no Font.Size or FontColor property, and we don't even have a style element to access in the Style Designer to make this kind of change. So, my next approach was to try to modify the text color in code. In RAD Studio XE3 and earlier, the only way that I was able to customize the size and color of a string grid's cells was to hook into the OnApplyStyle event for the individual cells. Fortunately, with XE4 and the introduction of FontColor and the StyledSettings properties, the process is much easier.

The trick, of course, is to get access to the individual cell controls (i.e. the TTextCell instances) and not just the strings in the Cells property. To do this, we can use the CellControlByRow method of a grid column. Unfortunately, the TColumn.CellControlByRow method was moved from the public section to protected in XE4. Therefore, in order to access this, we need to create a little helper class.

type
  TColumnAccess = class( TColumn )
  end;

Next, we need to modify the FormCreate event handler. After initializing a few of the Cells to show some actual text, I then iterate through the grid's Columns and for each column I use the CellControlByRow method to get the TTextCell instance. Using the reference to the actual cell control, we can change the various properties such as FontColor, Font.Size, and even Font.Family and Font.Style. Of course, for these changes to take effect, we must also change the StyledSettings property as shown below.

procedure TForm1.FormCreate(Sender: TObject);
var
  Col, Row: Integer;
  CellCtrl: TStyledControl;
begin
  StringGrid1.Cells[ 0, 0 ] := 'Cell00';
  StringGrid1.Cells[ 1, 0 ] := 'Cell10';

  StringGrid1.Cells[ 0, 1 ] := 'Cell01';
  StringGrid1.Cells[ 1, 1 ] := 'Cell11';

  for Col := 0 to StringGrid1.ColumnCount - 1 do
  begin
    for Row := 0 to StringGrid1.RowCount - 1 do
    begin
      CellCtrl := TColumnAccess( StringGrid1.Columns[ Col ] ).CellControlByRow( Row );
      if ( CellCtrl <> nil ) and ( CellCtrl is TTextCell ) then
      begin
        TTextCell( CellCtrl ).StyledSettings := [];
        TTextCell( CellCtrl ).FontColor := claBlueViolet;
        TTextCell( CellCtrl ).Font.Family := 'Times New Roman';
        TTextCell( CellCtrl ).Font.Style := [ TFontStyle.fsBold ];
        TTextCell( CellCtrl ).Font.Size := 14;
      end;
    end;
  end;
end;

Now, when I run the app, all of the cells of the string grid display their text in blue-violet using a 14 point Times New Roman font.

A final note regarding the FMX TStringGrid. The header cells for the grid are NOT handled by the Cells property. The text displayed in the grid's header is managed by each TStringColumn's Header property.

Ray Konopka
rkonopka@raize.com