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

RAD Delphi中GDI+沿圆形路径绘制字符串的实现求助

在RAD Delphi中用GDI+实现沿圆形半径环绕文本的方案

我帮你梳理了两种亲测可行的实现方式,解决你之前用DrawStringOnPath失败的问题,完全满足文本沿圆形半径环绕排列的需求👇

方法一:直接用DrawStringOnPath快速实现圆周环绕

这种方式最简洁,利用GDI+自带的路径文本绘制功能,几步就能搞定:

完整代码(窗体OnPaint事件中)

uses
  GDIPAPI, GDIPOBJ, GDIPUTIL;

procedure TForm1.FormPaint(Sender: TObject);
var
  Graphics: TGPGraphics;
  Path: TGPGraphicsPath;
  Font: TGPFont;
  Brush: TGPBrush;
  CenterX, CenterY, Radius: Single;
begin
  // 关联窗体画布创建GDI+图形对象
  Graphics := TGPGraphics.Create(Canvas.Handle);
  try
    // 开抗锯齿,让文本边缘更平滑
    Graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

    // 定义圆形的中心和半径(留20px边距避免超出窗体)
    CenterX := ClientWidth / 2;
    CenterY := ClientHeight / 2;
    Radius := Min(CenterX, CenterY) - 20;

    // 创建圆形路径(文本会附着在这个路径上)
    Path := TGPGraphicsPath.Create;
    try
      Path.AddEllipse(CenterX - Radius, CenterY - Radius, Radius * 2, Radius * 2);

      // 准备字体和画刷(这里用红色粗体Arial)
      Font := TGPFont.Create('Arial', 16, FontStyleBold, UnitPoint);
      Brush := TGPSolidBrush.Create(TGPColor.Create(255, 0, 0, 255));
      try
        // 核心:沿路径绘制文本
        // 参数依次是:文本内容、路径、起始偏移、字符间隔、字体、格式、画刷
        Graphics.DrawStringOnPath('Hello Delphi GDI+!', Path, 0, 0, Font, nil, Brush);
      finally
        Brush.Free;
        Font.Free;
      end;
    finally
      Path.Free;
    end;
  finally
    Graphics.Free;
  end;
end;

必加的GDI+初始化代码

别忘了在程序启动/退出时初始化GDI+,不然会报错:

var
  GdiplusToken: Cardinal;
  StartupInput: TGdiplusStartupInput;

procedure TForm1.FormCreate(Sender: TObject);
begin
  StartupInput.GdiplusVersion := 1;
  StartupInput.DebugEventCallback := nil;
  StartupInput.SuppressBackgroundThread := False;
  StartupInput.SuppressExternalCodecs := False;
  GdiplusStartup(GdiplusToken, @StartupInput, nil);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  GdiplusShutdown(GdiplusToken);
end;

踩坑提示

如果你之前用这个方法失败,大概率是这几个原因:

  • 没初始化GDI+:必须调用GdiplusStartup和GdiplusShutdown
  • 圆形路径位置不对:比如半径算太大,导致路径超出窗体可视区域
  • 字体/画刷创建失败:比如字体名称写错,或者Alpha通道设为0(完全透明)

方法二:逐个绘制字符,实现沿半径方向排列

如果需要每个字符的方向严格沿圆形半径(朝向或背离圆心),第一种方法可能不够灵活,这时候可以逐个计算字符的位置和旋转角度,精准控制每个字符的方向:

完整代码示例

procedure TForm1.FormPaint(Sender: TObject);
var
  Graphics: TGPGraphics;
  Font: TGPFont;
  Brush: TGPBrush;
  CenterX, CenterY, Radius, Angle, StepAngle: Single;
  Text: string;
  i: Integer;
  CharSize: TGPRectF;
begin
  Graphics := TGPGraphics.Create(Canvas.Handle);
  try
    Graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
    CenterX := ClientWidth / 2;
    CenterY := ClientHeight / 2;
    Radius := Min(CenterX, CenterY) - 40; // 留更大边距避免字符超出
    Text := '沿圆形半径排列的文本';
    Font := TGPFont.Create('微软雅黑', 14, FontStyleRegular, UnitPoint);
    Brush := TGPSolidBrush.Create(TGPColor.Create(255, 0, 0, 0)); // 黑色画刷
    try
      // 计算每个字符之间的角度间隔
      StepAngle := 2 * Pi / Length(Text);

      for i := 0 to Length(Text) - 1 do
      begin
        // 计算当前字符的角度(从顶部开始排列,减去Pi/2)
        Angle := i * StepAngle - Pi/2;

        // 保存当前图形状态,避免旋转影响后续绘制
        Graphics.Save;

        // 平移到圆形边缘的字符位置
        Graphics.TranslateTransform(CenterX + Cos(Angle)*Radius, CenterY + Sin(Angle)*Radius);
        // 旋转字符,使其沿半径方向(要朝向圆心就加Pi)
        Graphics.RotateTransform(RadToDeg(Angle));

        // 测量字符尺寸,让字符居中显示
        Graphics.MeasureString(Text[i+1], 1, Font, TGPRectF.Create(0,0,0,0), CharSize);
        // 向左上偏移一半尺寸,实现字符在目标点居中
        Graphics.DrawString(Text[i+1], 1, Font, TGPPointF.Create(-CharSize.Width/2, -CharSize.Height/2), Brush);

        // 恢复之前的图形状态
        Graphics.Restore;
      end;
    finally
      Brush.Free;
      Font.Free;
    end;
  finally
    Graphics.Free;
  end;
end;

这个方法可以完全自定义每个字符的角度、位置,甚至可以调整部分字符的大小、颜色,灵活性拉满。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:41:45