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

如何在Delphi的TMemo控件中添加行分隔线?

Delphi TMemo 行间添加实线的实现方案

TMemo控件本身没有内置的行分隔线属性,不过可以通过两种常用方式实现需求:

方法一:启用OwnerDraw自绘模式

通过设置OwnerDraw为True,重写OnDrawItem事件自定义每行的绘制逻辑,包括添加底线。

步骤与代码示例:

  1. 将TMemo的OwnerDraw属性设置为True
  2. 为OnDrawItem事件添加如下处理代码:
procedure TForm1.Memo1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  Memo: TMemo;
  LineText: string;
  TextRect: TRect;
begin
  Memo := Control as TMemo;
  LineText := Memo.Lines[Index];
  
  // 绘制行背景与文本(模拟默认样式)
  TextRect := Rect;
  InflateRect(TextRect, -2, 0); // 调整文本内边距
  Memo.Canvas.Font := Memo.Font;
  
  // 处理选中状态
  if odSelected in State then
  begin
    Memo.Canvas.Brush.Color := clHighlight;
    Memo.Canvas.Font.Color := clHighlightText;
  end
  else
  begin
    Memo.Canvas.Brush.Color := Memo.Color;
    Memo.Canvas.Font.Color := Memo.Font.Color;
  end;
  
  Memo.Canvas.FillRect(Rect);
  DrawText(Memo.Canvas.Handle, PChar(LineText), Length(LineText), TextRect, DT_LEFT or DT_VCENTER or DT_SINGLELINE);
  
  // 绘制行分隔实线
  Memo.Canvas.Pen.Color := clGray; // 可自定义线条颜色
  Memo.Canvas.MoveTo(Rect.Left, Rect.Bottom - 1);
  Memo.Canvas.LineTo(Rect.Right, Rect.Bottom - 1);
end;

注意点:

  • 自绘模式下需要自行处理选中、焦点等状态的样式
  • 可通过Pen.Width调整线条粗细,按需修改颜色参数

方法二:拦截WM_PAINT消息后追加绘制

如果不想完全接管自绘,可以通过继承TMemo并重写WM_PAINT消息,在默认绘制完成后追加线条。

代码示例:

type
  TMemoWithDividers = class(TMemo)
  protected
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  end;

procedure TMemoWithDividers.WMPaint(var Message: TWMPaint);
var
  DC: HDC;
  PS: TPaintStruct;
  I: Integer;
  LineTop, LineHeight: Integer;
  ClientRect: TRect;
begin
  inherited; // 先执行默认绘制逻辑
  
  DC := BeginPaint(Handle, PS);
  try
    GetClientRect(Handle, ClientRect);
    LineHeight := Canvas.TextHeight('X'); // 基于字体计算行高
    
    for I := 0 to Lines.Count - 1 do
    begin
      // 计算当前行底部位置
      LineTop := ClientRect.Top + (I + 1) * LineHeight;
      // 绘制横向实线
      MoveToEx(DC, ClientRect.Left, LineTop - 1, nil);
      LineTo(DC, ClientRect.Right, LineTop - 1);
    end;
  finally
    EndPaint(Handle, PS);
  end;
end;

注意点:

  • 这种方式更贴近原生TMemo的表现,但行高计算需考虑字体、行距等因素
  • 若Memo存在滚动条,需额外处理可见区域的线条绘制,避免无效绘制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:04:53