You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Delphi TStringGrid跨列绘制条形块时如何显示超长文本

解决方案:TStringGrid跨列绘制超长文本避免被覆盖

方法一:利用OnPaint事件(最可靠)

TStringGrid的OnPaint事件会在所有单元格的OnDrawCell执行完成后触发,此时绘制的文本不会被后续的单元格绘制操作覆盖。具体步骤如下:

  1. 修改OnDrawCell事件,仅处理背景和边框,移除原有的跨列文本绘制代码,并禁止默认文本绘制:
procedure TFVoDGraphicalPlannerForm.GRDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
  // 处理第2行5-10列的背景与边框
  if (ARow = 2) and (ACol >= 5) and (ACol <= 10) then begin
    GR.Canvas.Brush.Color := clBtnFace;
    GR.Canvas.FillRect(Rect);

    // 绘制左边界(仅第5列)
    if ACol = 5 then begin
      GR.Canvas.Pen.Width := 1;
      GR.Canvas.Pen.Color := clBlack;
      GR.Canvas.MoveTo(Rect.Left - 1, Rect.Top);
      GR.Canvas.LineTo(Rect.Left - 1, Rect.Bottom);
    end;

    // 绘制右边界(仅第10列)
    if ACol = 10 then begin
      GR.Canvas.Pen.Width := 1;
      GR.Canvas.Pen.Color := clBlack;
      GR.Canvas.MoveTo(Rect.Right - 1, Rect.Top);
      GR.Canvas.LineTo(Rect.Right - 1, Rect.Bottom);
    end;

    // 绘制上下边界(所有5-10列)
    GR.Canvas.Pen.Width := 1;
    GR.Canvas.Pen.Color := clBlack;
    GR.Canvas.MoveTo(Rect.Left, Rect.Top - 1);
    GR.Canvas.LineTo(Rect.Right, Rect.Top - 1);
    GR.Canvas.MoveTo(Rect.Left, Rect.Bottom - 1);
    GR.Canvas.LineTo(Rect.Right, Rect.Bottom - 1);

    // 跳过默认文本绘制,避免干扰自定义内容
    Exit;
  end;

  // 其他单元格保留默认绘制逻辑
  GR.DefaultDrawCell(ACol, ARow, Rect, State);
end;
  1. 为TStringGrid添加OnPaint事件,在其中计算跨列的整体区域并绘制文本:
procedure TFVoDGraphicalPlannerForm.GRPaint(Sender: TObject);
var
  FTotalRect: TRect;
  FLeftCellRect, FRightCellRect: TRect;
  FTxtFormat: TTextFormat;
  FTempStr: string;
begin
  // 计算第2行5-10列的整体显示区域
  FLeftCellRect := GR.CellRect(5, 2);
  FRightCellRect := GR.CellRect(10, 2);

  FTotalRect.Left := FLeftCellRect.Left + 5; // 保留原有的左边距
  FTotalRect.Top := FLeftCellRect.Top;
  FTotalRect.Right := FRightCellRect.Right;
  FTotalRect.Bottom := FLeftCellRect.Bottom;

  // 设置文本样式
  GR.Canvas.Font.Style := [fsBold];
  GR.Canvas.Font.Color := $009A9A9A;
  GR.Canvas.Font.Size := 14;

  // 绘制跨列文本
  FTempStr := 'Unusually long description that spans multiple columns and goes on and on...';
  FTxtFormat := [tfTop, tfLeft];
  GR.Canvas.TextRect(FTotalRect, FTempStr, FTxtFormat);
end;

方法二:在最后一列的DrawCell中绘制

TStringGrid默认按行从上到下、每行内从左到右的顺序绘制单元格,因此可以在目标区域的最后一列(第10列)中绘制跨列文本,此时不会被后续单元格覆盖:

修改OnDrawCell事件,将文本绘制逻辑移至第10列的处理分支中:

procedure TFVoDGraphicalPlannerForm.GRDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  FTotalRect: TRect;
  FTxtFormat: TTextFormat;
  FTempStr: string;
begin
  // 处理第2行5-10列的背景与边框
  if (ARow = 2) and (ACol >= 5) and (ACol <= 10) then begin
    GR.Canvas.Brush.Color := clBtnFace;
    GR.Canvas.FillRect(Rect);

    // 绘制左边界(仅第5列)
    if ACol = 5 then begin
      GR.Canvas.Pen.Width := 1;
      GR.Canvas.Pen.Color := clBlack;
      GR.Canvas.MoveTo(Rect.Left - 1, Rect.Top);
      GR.Canvas.LineTo(Rect.Left - 1, Rect.Bottom);
    end;

    // 绘制右边界+跨列文本(仅第10列)
    if ACol = 10 then begin
      GR.Canvas.Pen.Width := 1;
      GR.Canvas.Pen.Color := clBlack;
      GR.Canvas.MoveTo(Rect.Right - 1, Rect.Top);
      GR.Canvas.LineTo(Rect.Right - 1, Rect.Bottom);

      // 计算跨列文本的显示区域
      FTotalRect.Left := GR.CellRect(5, 2).Left + 5;
      FTotalRect.Top := GR.CellRect(5, 2).Top;
      FTotalRect.Right := Rect.Right;
      FTotalRect.Bottom := Rect.Bottom;

      // 设置文本样式并绘制
      GR.Canvas.Font.Style := [fsBold];
      GR.Canvas.Font.Color := $009A9A9A;
      GR.Canvas.Font.Size := 14;
      FTempStr := 'Unusually long description that spans multiple columns and goes on and on...';
      FTxtFormat := [tfTop, tfLeft];
      GR.Canvas.TextRect(FTotalRect, FTempStr, FTxtFormat);
    end;

    // 绘制上下边界(所有5-10列)
    GR.Canvas.Pen.Width := 1;
    GR.Canvas.Pen.Color := clBlack;
    GR.Canvas.MoveTo(Rect.Left, Rect.Top - 1);
    GR.Canvas.LineTo(Rect.Right, Rect.Top - 1);
    GR.Canvas.MoveTo(Rect.Left, Rect.Bottom - 1);
    GR.Canvas.LineTo(Rect.Right, Rect.Bottom - 1);

    // 跳过默认文本绘制
    Exit;
  end;

  // 其他单元格保留默认绘制逻辑
  GR.DefaultDrawCell(ACol, ARow, Rect, State);
end;

原理说明

  • 方法一通过OnPaint事件确保文本在所有单元格绘制完成后再渲染,彻底避免覆盖问题,适用于所有场景。
  • 方法二依赖TStringGrid默认的单元格绘制顺序,实现简单,但如果列的显示顺序被修改(如用户拖动列排序),可能会失效。

内容的提问来源于stack exchange,提问作者TomR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:14:50