donqiang的博客

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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);
        }
    }
}

 

 

 

效果如下图:

posted on 2015-04-02 15:59  donqiang  阅读(709)  评论(0)    收藏  举报