1

In firemonkey (RAD Studio 10.3), I am working with a TStringGrid connected to a database and I want to change the text alignment of a specific column. How can I do that? Changing HorzAlign in TextSettings property, changes the alignment of all columns.

I tried the suggested solution in this page and did not work! In newer versions of Firemonkey the below solution code results in an error.

type TSpecificColumn = class(TColumn)
protected
  function CreateCellControl: TStyledControl;override;
end;

There is no CreateCellControl function in TColumn Class anymore to be Overrided! This is the error I got:

Method CreateCellControl not found in base class.

Moj.H
  • 75
  • 12

2 Answers2

4

In the OnDrawColumnCell and/or OnDrawColumnHeader events you can use a TTextLayout for the purpose. As in the following example showing drawing the cells with three different alignments. The same can be applied when drawing the headers:

uses
  ...
  fmx.textlayout;


procedure TForm11.Grid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas;
  const Column: TColumn; const Bounds: TRectF; const Row: Integer;
  const Value: TValue; const State: TGridDrawStates);
var
  tl: TTextLayout;
  rf: TRectF;    // added
begin
  tl := TTextLayoutManager.DefaultTextLayout.Create;
  try
    tl.BeginUpdate;
    try
      // added from here
      rf := Bounds;
      InflateRect(rf, -2, -2);
      if (TGridDrawState.Selected in State) or
         (TGridDrawState.Focused in State) or
         (TGridDrawState.RowSelected in State)
      then
        Canvas.Fill.Color := TAlphaColors.LightBlue
      else
        Canvas.Fill.Color := TAlphaColors.White;

      Canvas.FillRect(rf, 0, 0, [], 1);
      // added until here

      tl.TopLeft := Bounds.TopLeft;
      tl.MaxSize := PointF(Column.Width, Column.Height);
      tl.Font.Size := 15;
      tl.Text := 'Some text'; // Value
      case Column.Index of
        0: tl.HorizontalAlign := TTextAlign.Leading;
        1: tl.HorizontalAlign := TTextAlign.Center;
        2: tl.HorizontalAlign := TTextAlign.Trailing;
      end;
    finally
      tl.EndUpdate;
    end;
    tl.RenderLayout(Canvas);
  finally
    tl.Free;
  end;
end;

enter image description here

TTextLayout has many other useful options and properties, so I recommend to take a look at the documentation.

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
  • Thank you for your great answer! Everything is working marvelously except one thing that I don't know what to do about it. As I mentioned in the question my StringGrid is connected to database table (through TBindSourceDB) for viewing and editing values. For the text property of created textlayout I did this: `tl.Text := value.ToString;` but now in every cell I have two text values on each other. [This is the image.](https://ibb.co/KWB3m8G) What's your suggestion? @Tom – Moj.H Jul 21 '19 at 04:38
  • For header I had this issue too. By adding `Column.Header := '';` in `OnDrawColumnHeader` event, headers got OK. But for cells containing the database values I have no Idea! These are [image#1](https://ibb.co/F4fS6Rw) and [image#2](https://ibb.co/4RgY2DV) for before and after solving the header problem. – Moj.H Jul 21 '19 at 05:12
  • Sorry to here. I can investigate further if you can provide me with an in-memory data set, the data binding and the relevant parts of the `.fmx` file (to assure my setup is equal) to reproduce the problem. Also include your version of the `OnDrawColumnCell()` event handler. – Tom Brunberg Jul 21 '19 at 07:15
  • I added some code to clear the cell before drawing anew. I leave it to you to select background colors for the various `TDrawStates`. This should work OK for both `TGrid` and `TStringGrid` but if not, please provide a test case as outlined in my previous comment. – Tom Brunberg Jul 21 '19 at 09:53
  • Thanks a million! Your new piece of code did the trick. In addition I changed `InflateRect(rf, -2, -2);` to `InflateRect(rf, 0, 0);` to completely cover the prevous values in cells. additionally I enabled AlternatingRowBackground in options and I had to consider background colors for alternate rows. As a solution I check if the row index is odd or even and I don't know if this is the correct way or the silly way! – Moj.H Jul 21 '19 at 11:05
  • There is only one problem remained! When I double click in a cell and it goes to editing mode, the text alignment goes back to default! For example, I set the alignment to "center" in `OnDrawColumnCell` event and the textalignment property in object inspector is set to "leading". In runtime the text alignment is "center", but when I double click the cell and it goes to editing mode, the text alignment returns to "leading". – Moj.H Jul 21 '19 at 11:11
  • Actually, text alignment doesn't change, although it may appear so. It appears so because of the internal editor, which is hard coded to open up at the left border of a cell and cover the whole cell area. Therefore the text in the editor is displayed at the left of the cell. The `TStringGrid` provides no means to show the editor at different positions. – Tom Brunberg Jul 21 '19 at 13:47
  • Ok, I got you. I'm very grateful for your help and thank you for your detailed answers. – Moj.H Jul 21 '19 at 14:17
0

Apart from the change already identified InflateRect(rf, 0, 0), to allow for existing data to be displayed correctly:

Change

tl.Text := 'Some text'; // Value line 

to

tl.Text := [StringGrid name property].Cells[Column.Index,Row];

This worked for me.

Ardent Coder
  • 3,777
  • 9
  • 27
  • 53
Rainer
  • 1