Stringgrid自动换行两次显示文本

Ash*_*lar 2 delphi vcl tstringgrid

我想以自动换行格式在字符串网格单元格中显示一个长字符串,并找到以下代码来做到这一点:

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
//enable wordwrap in cells
var
  S: String;
  drawrect :trect;
begin
  stringgrid1.Canvas.FillRect (Rect);
  S:= (Sender As TStringgrid).Cells [ACol, ARow ];
  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[Arow]
    Then
      (Sender As TStringgrid).RowHeights[Arow] :=
         (drawrect.bottom - drawrect.top)
      // changing the row height fires the event again!
    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;
Run Code Online (Sandbox Code Playgroud)

自动换行有效,但单元格同时显示原始文本和换行文本。我假设由于这是一个onDrawCell事件,因此原始文本已经绘制好了,我将用第一行代码(stringgrid1.canvas.fillrect(rect))将其擦除,但这对显示没有影响。失踪?

Tom*_*erg 5

...将使用第一行代码(stringgrid1.canvas.fillrect(rect)删除它,但这对显示没有影响

这是因为您在致电f.ex 之前没有选择Brush.Style(并且可能也Brush.Color)。FillRect()

  stringgrid1.canvas.Brush.Style := bsSolid; // add this line
  stringgrid1.canvas.Brush.Color := clWhite; // add this line
  stringgrid1.Canvas.FillRect (Rect);
Run Code Online (Sandbox Code Playgroud)

您会注意到,单元格左边缘的默认图形中有一些残留(在下图中不可见,我已经修复了它们)。那是因为TStringGrid内部将单元格绘图偏移了4个像素。要更改此Rect参数,您还需要在调用之前用-4 抵消参数的偏移量,并用+4增大宽度FillRect()

经过上述更改后,网格看起来非常平坦且暗淡(在图像中,我已经将颜色添加到了第二个网格中)。要恢复标题列和标题行的某些颜色gdFixed in State差异,您需要使用来处理带有的不同的单元格Brush.Color。具有的单元格相同gdSelected in State

在此处输入图片说明

以上是您取消勾选后还需要执行的操作DefaultDrawing。第二个网格和随附的代码对此进行了演示。请注意,代码还包含一个呼叫DrawFocusRect时,gdFocused in State刚刚结束之前。

请注意,我将所有这些Sender as TStringGrid替换为局部grid变量。

procedure TForm4.StringGrid2DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
var
  grid: TStringGrid;
  S: String;
  drawrect: TRect;
  bgFill: TColor;
begin
  grid := Sender as TStringGrid;

  if gdFixed in State then
    bgFill := $FFF8F8
  else
  if gdSelected in State then
    bgFill := $FFF0D0
  else
    bgFill := clWhite;

  grid.Canvas.Brush.Color := bgFill;
  grid.canvas.Brush.Style := bsSolid;
  grid.canvas.fillrect(Rect);

  S := grid.Cells[ACol, ARow];
  if Length(S) > 0 then
  begin
    drawrect := Rect;
    drawrect.Inflate(-4 , 0);
    DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
      dt_calcrect or dt_wordbreak or dt_left);
    If (drawrect.bottom - drawrect.top) > grid.RowHeights[ARow] then
      grid.RowHeights[ARow] := (drawrect.bottom - drawrect.top+2)
      // changing the row height fires the event again!
    else
    begin
      drawrect.Right := Rect.Right;

//      grid.canvas.fillrect(drawrect);
      DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
        dt_wordbreak or dt_left);
    end;
  end;

  if gdFocused in State then
    grid.Canvas.DrawFocusRect(Rect);
end;
Run Code Online (Sandbox Code Playgroud)

第三个网格显示了最简单的方法,而IMO则是最佳的解决方案,其中是TStringGrid完全跳过TDrawGrid而改为使用。您必须将要显示的数据分别保存在网格中的某个位置。我定义了一个数组:s_arr: array of array of string;

在这种情况下,您可以继续操作DefaultDrawing,因为TDrawGrid默认绘图期间不会绘制任何文本,因此内容绘图仅在OnDrawCell事件中发生。

procedure TForm4.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
var
  S: string;
  grid: TDrawGrid;
  drawrect: TRect;
begin
  grid := Sender as TDrawGrid;
  S := s_arr[ACol, ARow];
  If Length(S) > 0 Then
  Begin
    drawrect := Rect;
    drawrect.Inflate(-4 , 0);
    DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
      dt_calcrect or dt_wordbreak or dt_left);
    If (drawrect.bottom - drawrect.top) > grid.RowHeights[ARow] Then
      grid.RowHeights[ARow] := (drawrect.bottom - drawrect.top + 2)
      // changing the row height fires the event again!
    Else
    Begin
      drawrect.Right := Rect.Right;

      grid.canvas.fillrect(drawrect);
      DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect, dt_wordbreak or dt_left);
    End;
  End;
end;
Run Code Online (Sandbox Code Playgroud)

剩下的DefaultDrawing所有与主题相关的功能都是由网格本身绘制的,我们只在顶部绘制文本。