Как поместить CR / LF в ячейку TStringgrid? - PullRequest
7 голосов
/ 11 декабря 2010

Я хочу иметь одну фиксированную строку в качестве заголовка, но тексты довольно длинные, поэтому я бы хотел увеличить высоту строки и вставить CR / LF в текст ячейки.

Поиск в Google показывает это как решение (и это первое, что я подумал перед поиском в Google), но это не сработает. Есть идеи?

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

Что происходит, так это то, что клетка содержит This is a sample testThis is the second line

(Delphi 7, если это имеет какое-либо значение)

[Bounty] "Мой плохой. Я на самом деле наградил этот ответ два года назад, не проверяя, и теперь обнаружил, что ответ не сработал. Аплоги всем, кто был введен в заблуждение. Это FABOWAQ (часто задаваемый, часто ошибочно отвечаемый вопрос ). GINYF ".

Я предполагаю, что мы собираемся использовать OnDrawCell, но представьте, что нам также придется увеличить высоту строки сетки строк, содержащей ячейку.

Я получу ответ за код или компонент FOSS VCL.

[Обновление] должно работать с Delphi XE2 Starter edition

Ответы [ 2 ]

20 голосов
/ 24 октября 2012

TStringGrid использует Canvas.TextRect, который использует ExtTextOut, который, в свою очередь, не поддерживает рисование многострочного текста.

Вы должны нарисовать это самостоятельно в обработчике событий OnDrawCell с подпрограммой WinAPI DrawText. См., Например, этот ответ о том, как использовать DrawText для многострочного текста, и этот недавний ответ о том, как реализовать пользовательский рисунок в 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


Существуют также другие компоненты StringGrid, способные рисовать многострочный текст. Например, это , которое я написал сам (источники для скачивания: NLDStringGrid + NLDSparseList ), возможно, с таким результатом:

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;
5 голосов
/ 11 декабря 2010

Средство рендеринга TStringGrid по умолчанию не поддерживает несколько строк. Установив TStringGrid в режиме OwnerDraw (вызвав событие OnDrawCell), вы можете отобразить каждую ячейку по своему вкусу.

Посмотрите на этот пример, который помог предыдущему пользователю.

Вставлен связанный ссылочный код:

procedure DrawSGCell(Sender : TObject; C, R : integer; Rect : TRect;
          Style : TFontStyles; Wrap : boolean; Just : TAlignment;
          CanEdit : boolean);
  { draws formatted contents in string grid cell at col C, row R;
    Style is a set of fsBold, fsItalic, fsUnderline and fsStrikeOut;
    Wrap invokes word wrap for the cell's text; Just is taLeftJustify,
    taRightJustify or taCenter; if CanEdit false, cell will be given 
    the background color of fixed cells; call this routine from 
    grid's DrawCell event }
var
  S        : string;
  DrawRect : TRect;
begin
  with (Sender as tStringGrid), Canvas do begin
    { erase earlier contents from default drawing }
    if (R >= FixedRows) and (C >= FixedCols) and CanEdit then
      Brush.Color:= Color
    else
      Brush.Color:= FixedColor;
    FillRect(Rect);
    { get cell contents }
    S:= Cells[C, R];
    if length(S) > 0 then begin
      case Just of
        taLeftJustify  : S:= ' ' + S;
        taRightJustify : S:= S + ' ';
        end;
      { set font style }
      Font.Style:= Style;
      { copy of cell rectangle for text sizing }
      DrawRect:= Rect;
      if Wrap then begin
        { get size of text rectangle in DrawRect, with word wrap }
        DrawText(Handle, PChar(S), length(S), DrawRect,
          dt_calcrect or dt_wordbreak or dt_center);
        if (DrawRect.Bottom - DrawRect.Top) > RowHeights[R] then begin
          { cell word-wraps; increase row height }
          RowHeights[R]:= DrawRect.Bottom - DrawRect.Top;
          SetGridHeight(Sender as tStringGrid);
          end
        else begin
          { cell doesn't word-wrap }
          DrawRect.Right:= Rect.Right;
          FillRect(DrawRect);
          case Just of
            taLeftJustify  : DrawText(Handle, PChar(S), length(S), DrawRect,
                               dt_wordbreak or dt_left);
            taCenter       : DrawText(Handle, PChar(S), length(S), DrawRect,
                               dt_wordbreak or dt_center);
            taRightJustify : DrawText(Handle, PChar(S), length(S), DrawRect,
                               dt_wordbreak or dt_right);
            end;
          end
        end
      else
        { no word wrap }
        case Just of
          taLeftJustify  : DrawText(Handle, PChar(S), length(S), DrawRect,
                             dt_singleline or dt_vcenter or dt_left);
          taCenter       : DrawText(Handle, PChar(S), length(S), DrawRect,
                             dt_singleline or dt_vcenter or dt_center);
          taRightJustify : DrawText(Handle, PChar(S), length(S), DrawRect,
                             dt_singleline or dt_vcenter or dt_right);
          end;
      { restore no font styles }
      Font.Style:= [];
      end;
    end;
end;

Я думаю, это будет хорошо работать для вас ...

...