Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to put CR/LF into a TStringgrid cell?

I want to have one fixed row as a header, but the texts are rather long, so I'd like to increase the row height and insert CR/LF into the cell text.

Googling shows this as a solution (and it's the first thing I thought of before googling), but it doesn't seem to work. Any ideas?

Grid.Cells[2,3] := 'This is a sample test' + #13#10 + 'This is the second line';

What happens is that the cell contains This is a sample testThis is the second line

I am using Delphi 7 if it makes any difference.

[Bounty] "My bad. I actually awarded this an answer two years ago without checking and now find that the answer did not work. Apologies to anyone who was misled. This is a frequently asked, often wrongly answered question."

I presume that we are looking to use OnDrawCell, but imagine that we would also have to increase the height of the string grid row which contains the cell.

I will award the answer for either code or a FOSS VCL component.

[Update] must work with Delphi XE2 Starter edition

like image 413
Mawg says reinstate Monica Avatar asked Dec 11 '10 02:12

Mawg says reinstate Monica


1 Answers

TStringGrid uses Canvas.TextRect, which uses ExtTextOut, which in turn does not support drawing of multiline text.

You have to draw this yourself in an OnDrawCell event handler with WinAPI's DrawText routine. See for example this answer on how to use DrawText for multiline text, and this recent answer on how to implement custom drawing in OnDrawCell:

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
  private
    procedure FillWithRandomText(AGrid: TStringGrid);
    procedure UpdateRowHeights(AGrid: TStringGrid);
  end;

procedure TForm1.FillWithRandomText(AGrid: TStringGrid);
const
  S = 'This is a sample'#13#10'text that contains'#13#10'multiple lines.';
var
  X: Integer;
  Y: Integer;
begin
  for X := AGrid.FixedCols to AGrid.ColCount - 1 do
    for Y := AGrid.FixedRows to AGrid.RowCount - 1 do
      AGrid.Cells[X, Y] := Copy(S, 1, 8 + Random(Length(S) - 8));
  UpdateRowHeights(AGrid);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FillWithRandomText(StringGrid1);
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  with TStringGrid(Sender) do
    if Pos(#13#10, Cells[ACol, ARow]) > 0 then
    begin
      Canvas.FillRect(Rect);
      Inc(Rect.Left, 2);
      Inc(Rect.Top, 2);
      DrawText(Canvas.Handle, PChar(Cells[ACol, ARow]), -1, Rect,
        DT_NOPREFIX or DT_WORDBREAK);
    end;
end;

procedure TForm1.UpdateRowHeights(AGrid: TStringGrid);
var
  Y: Integer;
  MaxHeight: Integer;
  X: Integer;
  R: TRect;
  TxtHeight: Integer;
begin
  for Y := AGrid.FixedRows to AGrid.RowCount - 1 do
  begin
    MaxHeight := AGrid.DefaultRowHeight - 4;
    for X := AGrid.FixedCols to AGrid.ColCount - 1 do
    begin
      R := Rect(0, 0, AGrid.ColWidths[X] - 4, 0);
      TxtHeight := DrawText(AGrid.Canvas.Handle, PChar(AGrid.Cells[X, Y]), -1,
        R, DT_WORDBREAK or DT_CALCRECT);
      if TxtHeight > MaxHeight then
        MaxHeight := TxtHeight;
    end;
    AGrid.RowHeights[Y] := MaxHeight + 4;
  end;
end;

Default StringGrid


There are also other StringGrid components able of drawing multiline text. For instance, this one which I wrote myself (download source: NLDStringGrid) with possibly this result:

NLDStringGrid

var
  R: TRect;
begin
  NLDStringGrid1.Columns.Add;
  NLDStringGrid1.Columns.Add;
  NLDStringGrid1.Cells[1, 1] := 'Sample test'#13#10'Second line';
  NLDStringGrid1.Columns[1].MultiLine := True;
  NLDStringGrid1.AutoRowHeights := True;
  SetRect(R, 2, 2, 3, 3);
  NLDStringGrid1.MergeCells(TGridRect(R), True, True);
  NLDStringGrid1.ColWidths[2] := 40;
  NLDStringGrid1.Cells[2, 2] := 'Sample test'#13#10'Second line';
end;
like image 155
NGLN Avatar answered Oct 05 '22 17:10

NGLN