C#利用GDI+绘制旋转文字,矩形内可以根据布局方式排列文本
C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现。但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少。经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经过不少的计算过程。利用下面的类可以实现该功能。
1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System.Drawing.Drawing2D; 5 6 namespace RotateText 7 { 8 public class GraphicsText 9 { 10 private Graphics _graphics; 11 12 public GraphicsText() 13 { 14 15 } 16 17 public Graphics Graphics 18 { 19 get { return _graphics; } 20 set { _graphics = value; } 21 } 22 23 /// <summary> 24 /// 绘制根据矩形旋转文本 25 /// </summary> 26 /// <param name="s">文本</param> 27 /// <param name="font">字体</param> 28 /// <param name="brush">填充</param> 29 /// <param name="layoutRectangle">局部矩形</param> 30 /// <param name="format">布局方式</param> 31 /// <param name="angle">角度</param> 32 public void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format, float angle) 33 { 34 // 求取字符串大小 35 SizeF size = _graphics.MeasureString(s, font); 36 37 // 根据旋转角度,求取旋转后字符串大小 38 SizeF sizeRotate = ConvertSize(size, angle); 39 40 // 根据旋转后尺寸、布局矩形、布局方式计算文本旋转点 41 PointF rotatePt = GetRotatePoint(sizeRotate, layoutRectangle, format); 42 43 // 重设布局方式都为Center 44 StringFormat newFormat = new StringFormat(format); 45 newFormat.Alignment = StringAlignment.Center; 46 newFormat.LineAlignment = StringAlignment.Center; 47 48 // 绘制旋转后文本 49 DrawString(s, font, brush, rotatePt, newFormat, angle); 50 } 51 52 /// <summary> 53 /// 绘制根据点旋转文本,一般旋转点给定位文本包围盒中心点 54 /// </summary> 55 /// <param name="s">文本</param> 56 /// <param name="font">字体</param> 57 /// <param name="brush">填充</param> 58 /// <param name="point">旋转点</param> 59 /// <param name="format">布局方式</param> 60 /// <param name="angle">角度</param> 61 public void DrawString(string s, Font font, Brush brush, PointF point, StringFormat format, float angle) 62 { 63 // Save the matrix 64 Matrix mtxSave = _graphics.Transform; 65 66 Matrix mtxRotate = _graphics.Transform; 67 mtxRotate.RotateAt(angle, point); 68 _graphics.Transform = mtxRotate; 69 70 _graphics.DrawString(s, font, brush, point, format); 71 72 // Reset the matrix 73 _graphics.Transform = mtxSave; 74 } 75 76 private SizeF ConvertSize(SizeF size, float angle) 77 { 78 Matrix matrix = new Matrix(); 79 matrix.Rotate(angle); 80 81 // 旋转矩形四个顶点 82 PointF[] pts = new PointF[4]; 83 pts[0].X = -size.Width / 2f; 84 pts[0].Y = -size.Height / 2f; 85 pts[1].X = -size.Width / 2f; 86 pts[1].Y = size.Height / 2f; 87 pts[2].X = size.Width / 2f; 88 pts[2].Y = size.Height / 2f; 89 pts[3].X = size.Width / 2f; 90 pts[3].Y = -size.Height / 2f; 91 matrix.TransformPoints(pts); 92 93 // 求取四个顶点的包围盒 94 float left = float.MaxValue; 95 float right = float.MinValue; 96 float top = float.MaxValue; 97 float bottom = float.MinValue; 98 99 foreach(PointF pt in pts) 100 { 101 // 求取并集 102 if(pt.X < left) 103 left = pt.X; 104 if(pt.X > right) 105 right = pt.X; 106 if(pt.Y < top) 107 top = pt.Y; 108 if(pt.Y > bottom) 109 bottom = pt.Y; 110 } 111 112 SizeF result = new SizeF(right - left, bottom - top); 113 return result; 114 } 115 116 private PointF GetRotatePoint(SizeF size, RectangleF layoutRectangle, StringFormat format) 117 { 118 PointF pt = new PointF(); 119 120 switch (format.Alignment) 121 { 122 case StringAlignment.Near: 123 pt.X = layoutRectangle.Left + size.Width / 2f; 124 break; 125 case StringAlignment.Center: 126 pt.X = (layoutRectangle.Left + layoutRectangle.Right) / 2f; 127 break; 128 case StringAlignment.Far: 129 pt.X = layoutRectangle.Right - size.Width / 2f; 130 break; 131 default: 132 break; 133 } 134 135 switch (format.LineAlignment) 136 { 137 case StringAlignment.Near: 138 pt.Y = layoutRectangle.Top + size.Height / 2f; 139 break; 140 case StringAlignment.Center: 141 pt.Y = (layoutRectangle.Top + layoutRectangle.Bottom) / 2f; 142 break; 143 case StringAlignment.Far: 144 pt.Y = layoutRectangle.Bottom - size.Height / 2f; 145 break; 146 default: 147 break; 148 } 149 150 return pt; 151 } 152 } 153 }
测试代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; namespace RotateText { public partial class FormMain : Form { private Font _font = new Font("Arial", 12); private Brush _brush = new SolidBrush(Color.Black); private Pen _pen = new Pen(Color.Black, 1f); private string _text = "Crow Soft"; public FormMain() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); GraphicsText graphicsText = new GraphicsText(); graphicsText.Graphics = e.Graphics; // 绘制围绕点旋转的文本 StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; graphicsText.DrawString(_text, _font, _brush, new PointF(100, 80), format, 45f); graphicsText.DrawString(_text, _font, _brush, new PointF(200, 80), format, -45f); graphicsText.DrawString(_text, _font, _brush, new PointF(300, 80), format, 90f); graphicsText.DrawString(_text, _font, _brush, new PointF(400, 80), format, -60f); // 绘制矩形内旋转的文本 // First line RectangleF rc = RectangleF.FromLTRB(50, 150, 200, 230); RectangleF rect = rc; format.Alignment = StringAlignment.Near; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 30); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Near; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, -30); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Center; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, -90); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Far; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 70); // Second line rect = rc; rect.Location += new SizeF(0, 100); format.Alignment = StringAlignment.Center; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 40); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Near; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 30); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Center; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, -70); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Far; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 60); // Third line rect = rc; rect.Location += new SizeF(0, 200); format.Alignment = StringAlignment.Far; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, -30); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Near; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, -30); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Center; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 90); rect.Location += new SizeF(180, 0); format.LineAlignment = StringAlignment.Far; e.Graphics.DrawRectangle(_pen, rect.Left, rect.Top, rect.Width, rect.Height); graphicsText.DrawString(_text, _font, _brush, rect, format, 45); } } }
效果如下图:
浙公网安备 33010602011771号