Having messed with this some more I have found a solution which answers my problem
The money symbol is obtained by using the OnGetText event of the dataset field to return the formatted string:
procedure FDTableMyCurrFieldGetText(Sender: TField; var Text: string;
DisplayText: Boolean);
begin
DisplayText := True;
Text := FloatToStrF(Sender.AsCurrency, ffCurrency, 18, 2);
end;
I could have done this in the Grid OnPainting event but doing it this way formats the field for all linked controls as well as for the grid. I use "Sender" rather than "FDTableMyCurrField" to refer to the Field so that I can point the OnGetText event of all the other currency fields in my datasets to this method.
The rest of the formatting is done in the Grid. The Cells of the Grid are not exposed explicitly but you can get to them like this "TTextCell(Grid1.Columns[I].Children[J])". Use the Grid OnPainting event to format the cells immediately before they are painted.
Right alignment is achieved by setting the alignment of the Cell in the grid.
The cell text color is set by using Styles.
We need to create a "textcellnegativestyle" in our application StyleBook. This will be identical to the default "textcellstyle" except that the "foreground" Brush colour will be red.
On a desktop application you could drop a TEdit on your application, right-click it and select "Edit Custom Style..." then name the custom style "textcellnegativestyle" based on the "editstyle" but just change the foreground Brush color to red.
Mine is a mobile app where "Edit Custom Style" does not appear on the Delphi form editor popup menu options for this reason.
To add a custom style you have to edit (a copy of) the .style file with Notepad or some text editor.
- Copy/paste the "textcellstyle" object
- edit the name of the pasted object to "textcellnegativestyle"
- change the 'foreground' Brush color to red.
- Load the edited file into your application StyleBook.
Here is how it looks in my .style file:
object TLayout
StyleName = 'textcellnegativestyle'
DesignVisible = False
Height = 50.000000000000000000
Width = 50.000000000000000000
object TLayout
StyleName = 'content'
Align = alContents
Locked = True
Height = 42.000000000000000000
Margins.Left = 4.000000000000000000
Margins.Top = 4.000000000000000000
Margins.Right = 4.000000000000000000
Margins.Bottom = 4.000000000000000000
Width = 42.000000000000000000
end
object TBrushObject
StyleName = 'foreground'
Brush.Color = claRed
end
object TBrushObject
StyleName = 'selection'
Brush.Color = x7F72B6E6
end
object TFontObject
StyleName = 'font'
end
end
I use the Grid OnPainting event to set the Cells alignment and style. here is my working solution:
procedure TFormMain.Grid1Painting(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
var
I, J: Integer;
T: TTextCell;
begin
// my Column 0 is text, all other columns are money in this example
for I := 1 to Grid1.ColumnCount - 1 do
for J := 0 to Grid1.Columns[I].ChildrenCount- 1 do
begin
T := TTextCell(Grid1.Columns[I].Children[J]);
// set the Cell text alignment to right align
T.TextAlign := TTextAlign.taTrailing;
// test the Cell string for a negative value
if (T.Text[1] = '-') then
begin
// remove the leading minus sign
T.Text := Copy(T.Text, 2, Length(T.Text) - 1);
// set the font to red using the style
T.StyleLookup := 'textcellnegativestyle';
end
else T.StyleLookup := 'textcellstyle';
end;
end;