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
相关产品推荐
相关产品推荐

