Mirror

Display multiple lines in a single cell of a TStringGrid (Views: 100)


Problem/Question/Abstract:

How to display multiple lines in a single cell of a TStringGrid

Answer:

Solve 1:

It is fairly easy to draw such text in an OnDrawCell handler. However the standard inplace editor of a grid is not well prepared to handle cells higher than one line.

procedure TForm1.StringGrid1DrawCell(Sender: TObject; Col, Row: Integer;
  Rect: TRect; State: TGridDrawState);
var
  S: string;
  drawrect: TRect;
begin
  S := (Sender as TStringGrid).Cells[Col, Row];
  if Length(S) > 0 then
  begin
    drawrect := rect;
    DrawText((Sender as TStringGrid).canvas.handle, Pchar(S), Length(S), drawrect,
      DT_CALCRECT or DT_WORDBREAK or DT_LEFT);
    if (drawrect.bottom - drawrect.top) > (Sender as TStringGrid).RowHeights[row] then
      (Sender as TStringGrid).RowHeights[row] := (drawrect.bottom - drawrect.top)
    else
    begin
      drawrect.Right := rect.right;
      (Sender as TStringGrid).canvas.fillrect(drawrect);
      DrawText((Sender as TStringGrid).canvas.handle, Pchar(S), Length(S),
        drawrect, DT_WORDBREAK or DT_LEFT);
    end;
  end;
end;

It will automatically adjust the row height to larger values if needed. The main problem is that it will not automatically decrease the row height if the text would fit into a smaller row. It cannot do that since there may be other cells in the row that need a taller row. You could fix that problem by setting the rowheigh back to the defaultrowheight when you change the cell data for a row, that would trigger a redraw and that in turn would adjust the rowheight to what is needed. It would cause some flicker, though.


Solve 2:

This is a unit that enables word-wrap in a cell of a TStringGrid:

unit Unit1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, ExtCtrls, Grids;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Panel1: TPanel;
    procedure StringGrid1DrawCell(Sender: TObject; Col, Row: Longint;
      Rect: TRect; State: TGridDrawState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.StringGrid1DrawCell(Sender: TObject; Col, Row: Longint;
  Rect: TRect; State: TGridDrawState);
var
  A: array[0..255] of char;
  drawrect: TRect;
begin
  StrPCopy(A, (Sender as TStringgrid).Cells[Col, Row]);
  if StrLen(A) > 0 then
    with (Sender as TStringgrid) do
    begin
      drawrect := rect;
      {Note that the first DrawText uses the DT_CALCRECT flag to calculate a new
                        value for drawrect. This value is used to set the RowHeights
                        parameter if necessary.}
      DrawText(canvas.handle, A, -1, drawrect, DT_CALCRECT or DT_WORDBREAK or
        DT_LEFT);
      if (drawrect.bottom - drawrect.top) > RowHeights[Row] then
        RowHeights[row] := (drawrect.bottom - drawrect.top)
      else
      begin
        drawrect.right := rect.right;
        canvas.fillrect(drawrect);
        DrawText(canvas.handle, A, -1, drawrect, DT_WORDBREAK or DT_LEFT);
      end;
    end;
end;

end.

<< Back to main page