using System.Drawing; namespace System.Windows.Forms { public static class TextRenderer { private static Graphics measureGraphics = Graphics.FromImage(new Bitmap(1, 1)); private static StringFormat GetStringFormat(TextFormatFlags flags) { var format = new StringFormat(StringFormat.GenericTypographic); var rtl = false; if ((flags & TextFormatFlags.RightToLeft) != 0) { format.FormatFlags |= StringFormatFlags.DirectionRightToLeft; rtl = true; } if ((flags & TextFormatFlags.HorizontalCenter) != 0) format.Alignment = StringAlignment.Center; if ((flags & TextFormatFlags.Right) != 0) format.Alignment = rtl ? StringAlignment.Near : StringAlignment.Far; if ((flags & TextFormatFlags.VerticalCenter) != 0) format.LineAlignment = StringAlignment.Center; if ((flags & TextFormatFlags.Bottom) != 0) format.LineAlignment = StringAlignment.Far; if ((flags & TextFormatFlags.EndEllipsis) != 0) { format.Trimming = StringTrimming.EllipsisCharacter; format.FormatFlags |= StringFormatFlags.NoWrap; } else format.Trimming = StringTrimming.Character; format.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Hide; format.FormatFlags &= ~StringFormatFlags.LineLimit; return format; } private static void Transform(Graphics g, TextFormatFlags flags) { var offset = new PointF(g.Transform.OffsetX, g.Transform.OffsetY); g.ResetTransform(); if ((flags & TextFormatFlags.PreserveGraphicsTranslateTransform) != 0) g.TranslateTransform(offset.X, offset.Y); } public static void DrawText(Graphics g, string text, Font font, System.Drawing.Point pos, Color foreColor, TextFormatFlags flags) { using (StringFormat format = GetStringFormat(flags)) using (SolidBrush brush = new SolidBrush(foreColor)) { var state = g.Save(); Transform(g, flags); if ((flags & TextFormatFlags.RightToLeft) != 0) { pos.X += MeasureText(text, font).Width - 4; } g.DrawString(text, font, brush, pos.X + 2, pos.Y, format); g.Restore(state); } } public static void DrawText(Graphics g, string text, Font font, System.Drawing.Point pos, Color foreColor) => DrawText(g, text, font, pos, foreColor, TextFormatFlags.Default); public static void DrawText(Graphics g, string text, Font font, Rectangle rect, Color foreColor, TextFormatFlags flags) { using (StringFormat format = GetStringFormat(flags)) using (SolidBrush brush = new SolidBrush(foreColor)) { var state = g.Save(); Transform(g, flags); g.DrawString(text, font, brush, new Rectangle(rect.X + 2, rect.Y, rect.Width - 4, rect.Height), format); g.Restore(state); } } public static void DrawText(Graphics g, string text, Font font, Rectangle rect, Color foreColor) => DrawText(g, text, font, rect, foreColor, TextFormatFlags.Default); public static void DrawText(Graphics g, string text, Font font, Rectangle rect, Color foreColor, Color backColor, TextFormatFlags flags) => DrawText(g, text, font, rect, foreColor, flags); public static System.Drawing.Size MeasureText(string text, Font font) => MeasureString(text, font).ToSize(); public static System.Drawing.Size MeasureText(string text, Font font, Drawing.Size size) => MeasureString(text, font, size.Width, StringFormat.GenericTypographic).ToSize(); public static SizeF MeasureString(string text, Font font) => measureGraphics.MeasureString(text, font); public static SizeF MeasureString(string text, Font font, int maxWidth, StringFormat format) => measureGraphics.MeasureString(text, font, maxWidth, format); } [Flags] public enum TextFormatFlags { Bottom = 0x8, EndEllipsis = 0x8000, ExpandTabs = 0x40, ExternalLeading = 0x200, Default = 0x0, HidePrefix = 0x100000, HorizontalCenter = 0x1, Internal = 0x1000, Left = 0x0, ModifyString = 0x10000, NoClipping = 0x100, NoPrefix = 0x800, NoFullWidthCharacterBreak = 0x80000, PathEllipsis = 0x4000, PrefixOnly = 0x200000, Right = 0x2, RightToLeft = 0x20000, SingleLine = 0x20, TextBoxControl = 0x2000, Top = 0x0, VerticalCenter = 0x4, WordBreak = 0x10, WordEllipsis = 0x40000, PreserveGraphicsClipping = 0x1000000, PreserveGraphicsTranslateTransform = 0x2000000, GlyphOverhangPadding = 0x0, NoPadding = 0x10000000, LeftAndRightPadding = 0x20000000 } }