4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2006 Novell, Inc.
26 // Jonathan Pobst (monkey@jpobst.com)
31 using System.Runtime.InteropServices;
33 using System.Drawing.Text;
35 namespace System.Windows.Forms
37 public sealed class TextRenderer
39 private TextRenderer ()
43 #region Public Methods
44 [MonoTODO("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
45 public static void DrawText (IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags)
47 if (text == null || text.Length == 0)
50 if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
51 Rectangle new_bounds = bounds;
52 new_bounds.Offset ((int)(dc as Graphics).Transform.OffsetX + 0, (int)(dc as Graphics).Transform.OffsetY + 0);
53 IntPtr hdc = dc.GetHdc ();
55 SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));
56 SetBkMode (hdc, 1); //1-Transparent, 2-Opaque
58 VisualStyles.UXTheme.RECT r = VisualStyles.UXTheme.RECT.FromRectangle (new_bounds);
61 SelectObject (hdc, font.ToHfont ());
63 DrawText (hdc, text, text.Length, ref r, (int)flags);
72 g = Graphics.FromHdc (dc.GetHdc ());
74 StringFormat sf = FlagsToStringFormat (flags);
76 using (Brush b = new SolidBrush (foreColor))
77 g.DrawString (text, font, b, bounds, sf);
79 if (!(dc is Graphics)) {
86 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
87 public static void DrawText (IDeviceContext dc, string text, Font font, Point pt, Color foreColor, TextFormatFlags flags)
89 if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
90 IntPtr hdc = dc.GetHdc ();
92 SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));
93 SetBkMode (hdc, 1); //1-Transparent, 2-Opaque
95 Size sz = MeasureText(text, font);
97 VisualStyles.UXTheme.RECT r = new System.Windows.Forms.VisualStyles.UXTheme.RECT(pt.X, pt.Y, pt.X + sz.Width, pt.Y + sz.Height);
100 SelectObject (hdc, font.ToHfont ());
102 DrawText (hdc, text, text.Length, ref r, (int)flags);
111 g = Graphics.FromHdc (dc.GetHdc ());
113 StringFormat sf = FlagsToStringFormat (flags);
115 using (Brush b = new SolidBrush (foreColor))
116 g.DrawString (text, font, b, pt, sf);
118 if (!(dc is Graphics)) {
125 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
126 public static Size MeasureText (string text, Font font)
128 if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
129 Bitmap b = new Bitmap (5, 5);
130 Graphics g = Graphics.FromImage (b);
132 IntPtr hdc = g.GetHdc ();
135 SelectObject (hdc, font.ToHfont ());
137 VisualStyles.UXTheme.SIZE text_size = new System.Windows.Forms.VisualStyles.UXTheme.SIZE();
139 GetTextExtentPoint32 (hdc, text, text.Length, out text_size);
143 Size retval = text_size.ToSize();
144 //retval.Height += 4;
145 if (retval.Width > 0) retval.Width += 6;
149 Bitmap b = new Bitmap (5, 5);
150 Graphics g = Graphics.FromImage (b);
152 Size retval = g.MeasureString(text,font).ToSize();
153 if (retval.Width > 0) retval.Width += 6;
158 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
159 public static Size MeasureText (string text, Font font, Size proposedSize, TextFormatFlags flags)
161 if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
162 if ((flags & TextFormatFlags.HidePrefix) == TextFormatFlags.HidePrefix)
164 text = text.Replace ("&", "");
167 Bitmap b = new Bitmap (5, 5);
168 Graphics g = Graphics.FromImage (b);
170 IntPtr hdc = g.GetHdc ();
173 SelectObject (hdc, font.ToHfont ());
175 VisualStyles.UXTheme.SIZE text_size = new System.Windows.Forms.VisualStyles.UXTheme.SIZE ();
177 GetTextExtentPoint32 (hdc, text, text.Length, out text_size);
181 Size retval = text_size.ToSize ();
182 //retval.Height += 4;
183 if (retval.Width > 0) retval.Width += 6;
187 Bitmap b = new Bitmap (5, 5);
188 Graphics g = Graphics.FromImage (b);
190 Size retval = g.MeasureString (text, font).ToSize ();
191 if (retval.Width > 0) retval.Width += 6;
197 #region Private Methods
198 private static StringFormat FlagsToStringFormat (TextFormatFlags flags)
200 StringFormat sf = new StringFormat ();
202 // Translation table: http://msdn.microsoft.com/msdnmag/issues/06/03/TextRendering/default.aspx?fig=true#fig4
204 // Horizontal Alignment
205 if ((flags & TextFormatFlags.HorizontalCenter) == TextFormatFlags.HorizontalCenter)
206 sf.Alignment = StringAlignment.Center;
207 else if ((flags & TextFormatFlags.Right) == TextFormatFlags.Right)
208 sf.Alignment = StringAlignment.Far;
210 sf.Alignment = StringAlignment.Near;
212 // Vertical Alignment
213 if ((flags & TextFormatFlags.Bottom) == TextFormatFlags.Bottom)
214 sf.LineAlignment = StringAlignment.Far;
215 else if ((flags & TextFormatFlags.VerticalCenter) == TextFormatFlags.VerticalCenter)
216 sf.LineAlignment = StringAlignment.Center;
218 sf.LineAlignment = StringAlignment.Near;
221 if ((flags & TextFormatFlags.EndEllipsis) == TextFormatFlags.EndEllipsis)
222 sf.Trimming = StringTrimming.EllipsisCharacter;
223 else if ((flags & TextFormatFlags.PathEllipsis) == TextFormatFlags.PathEllipsis)
224 sf.Trimming = StringTrimming.EllipsisPath;
225 else if ((flags & TextFormatFlags.WordEllipsis) == TextFormatFlags.WordEllipsis)
226 sf.Trimming = StringTrimming.EllipsisWord;
228 sf.Trimming = StringTrimming.Character;
231 if ((flags & TextFormatFlags.NoPrefix) == TextFormatFlags.NoPrefix)
232 sf.HotkeyPrefix = HotkeyPrefix.None;
233 else if ((flags & TextFormatFlags.HidePrefix) == TextFormatFlags.HidePrefix)
234 sf.HotkeyPrefix = HotkeyPrefix.Hide;
236 sf.HotkeyPrefix = HotkeyPrefix.Show;
239 if ((flags & TextFormatFlags.NoPadding) == TextFormatFlags.NoPadding)
240 sf.FormatFlags |= StringFormatFlags.FitBlackBox;
243 if ((flags & TextFormatFlags.SingleLine) == TextFormatFlags.SingleLine)
244 sf.FormatFlags |= StringFormatFlags.NoWrap;
245 else if ((flags & TextFormatFlags.TextBoxControl) == TextFormatFlags.TextBoxControl)
246 sf.FormatFlags |= StringFormatFlags.LineLimit;
249 if ((flags & TextFormatFlags.RightToLeft) == TextFormatFlags.RightToLeft)
250 sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
251 if ((flags & TextFormatFlags.NoClipping) == TextFormatFlags.NoClipping)
252 sf.FormatFlags |= StringFormatFlags.NoClip;
253 sf.FormatFlags |= StringFormatFlags.NoClip;
259 #region DllImports (Windows)
260 [DllImport ("user32", CharSet = CharSet.Unicode)]
261 static extern int DrawText (IntPtr hdc, string lpStr, int nCount, ref VisualStyles.UXTheme.RECT lpRect, int wFormat);
263 [DllImport ("gdi32")]
264 static extern int SetTextColor (IntPtr hdc, int crColor);
266 [DllImport ("gdi32")]
267 private extern static IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
269 //[DllImport ("gdi32")]
270 //static extern int SetBkColor (IntPtr hdc, int crColor);
272 [DllImport ("gdi32")]
273 static extern int SetBkMode (IntPtr hdc, int iBkMode);
275 //[DllImport ("gdi32")]
276 //static extern bool GetTextExtentExPoint (IntPtr hdc, string lpszStr, int cchString, int nMaxExtent, IntPtr lpnFit, IntPtr alpDx, out VisualStyles.UXTheme.SIZE lpSize);
278 [DllImport ("gdi32")]
279 static extern bool GetTextExtentPoint32 (IntPtr hdc, string lpString, int cbString, out VisualStyles.UXTheme.SIZE lpSize);