TextRenderer.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. //
  2. // TextRenderer.cs
  3. //
  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:
  11. //
  12. // The above copyright notice and this permission notice shall be
  13. // included in all copies or substantial portions of the Software.
  14. //
  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.
  22. //
  23. // Copyright (c) 2006 Novell, Inc.
  24. //
  25. // Authors:
  26. // Jonathan Pobst ([email protected])
  27. //
  28. #if NET_2_0
  29. using System.Drawing;
  30. using System.Runtime.InteropServices;
  31. using System.Text;
  32. using System.Drawing.Text;
  33. namespace System.Windows.Forms
  34. {
  35. public sealed class TextRenderer
  36. {
  37. private TextRenderer ()
  38. {
  39. }
  40. #region Public Methods
  41. [MonoTODO("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
  42. public static void DrawText (IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags)
  43. {
  44. if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
  45. Rectangle new_bounds = bounds;
  46. new_bounds.Offset ((int)(dc as Graphics).Transform.OffsetX + 0, (int)(dc as Graphics).Transform.OffsetY + 0);
  47. IntPtr hdc = dc.GetHdc ();
  48. SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));
  49. SetBkMode (hdc, 1); //1-Transparent, 2-Opaque
  50. VisualStyles.UXTheme.RECT r = VisualStyles.UXTheme.RECT.FromRectangle (new_bounds);
  51. if (font != null)
  52. SelectObject (hdc, font.ToHfont ());
  53. DrawText (hdc, text, text.Length, ref r, (int)flags);
  54. dc.ReleaseHdc ();
  55. }
  56. else {
  57. Graphics g;
  58. if (dc is Graphics)
  59. g = (Graphics)dc;
  60. else
  61. g = Graphics.FromHdc (dc.GetHdc ());
  62. StringFormat sf = FlagsToStringFormat (flags);
  63. using (Brush b = new SolidBrush (foreColor))
  64. g.DrawString (text, font, b, bounds, sf);
  65. if (!(dc is Graphics)) {
  66. g.Dispose ();
  67. dc.ReleaseHdc ();
  68. }
  69. }
  70. }
  71. [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
  72. public static void DrawText (IDeviceContext dc, string text, Font font, Point pt, Color foreColor, TextFormatFlags flags)
  73. {
  74. if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
  75. IntPtr hdc = dc.GetHdc ();
  76. SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));
  77. SetBkMode (hdc, 1); //1-Transparent, 2-Opaque
  78. Size sz = MeasureText(text, font);
  79. VisualStyles.UXTheme.RECT r = new System.Windows.Forms.VisualStyles.UXTheme.RECT(pt.X, pt.Y, pt.X + sz.Width, pt.Y + sz.Height);
  80. if (font != null)
  81. SelectObject (hdc, font.ToHfont ());
  82. DrawText (hdc, text, text.Length, ref r, (int)flags);
  83. dc.ReleaseHdc ();
  84. }
  85. else {
  86. Graphics g;
  87. if (dc is Graphics)
  88. g = (Graphics)dc;
  89. else
  90. g = Graphics.FromHdc (dc.GetHdc ());
  91. StringFormat sf = FlagsToStringFormat (flags);
  92. using (Brush b = new SolidBrush (foreColor))
  93. g.DrawString (text, font, b, pt, sf);
  94. if (!(dc is Graphics)) {
  95. g.Dispose ();
  96. dc.ReleaseHdc ();
  97. }
  98. }
  99. }
  100. [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
  101. public static Size MeasureText (string text, Font font)
  102. {
  103. if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
  104. Bitmap b = new Bitmap (5, 5);
  105. Graphics g = Graphics.FromImage (b);
  106. IntPtr hdc = g.GetHdc ();
  107. if (font != null)
  108. SelectObject (hdc, font.ToHfont ());
  109. VisualStyles.UXTheme.SIZE text_size = new System.Windows.Forms.VisualStyles.UXTheme.SIZE();
  110. GetTextExtentPoint32 (hdc, text, text.Length, out text_size);
  111. g.ReleaseHdc();
  112. Size retval = text_size.ToSize();
  113. //retval.Height += 4;
  114. if (retval.Width > 0) retval.Width += 6;
  115. return retval;
  116. }
  117. else {
  118. Bitmap b = new Bitmap (5, 5);
  119. Graphics g = Graphics.FromImage (b);
  120. Size retval = g.MeasureString(text,font).ToSize();
  121. if (retval.Width > 0) retval.Width += 6;
  122. return retval;
  123. }
  124. }
  125. #endregion
  126. #region Private Methods
  127. private static StringFormat FlagsToStringFormat (TextFormatFlags flags)
  128. {
  129. StringFormat sf = new StringFormat ();
  130. // Translation table: http://msdn.microsoft.com/msdnmag/issues/06/03/TextRendering/default.aspx?fig=true#fig4
  131. // Horizontal Alignment
  132. if ((flags & TextFormatFlags.HorizontalCenter) == TextFormatFlags.HorizontalCenter)
  133. sf.Alignment = StringAlignment.Center;
  134. else if ((flags & TextFormatFlags.Right) == TextFormatFlags.Right)
  135. sf.Alignment = StringAlignment.Far;
  136. else
  137. sf.Alignment = StringAlignment.Near;
  138. // Vertical Alignment
  139. if ((flags & TextFormatFlags.Bottom) == TextFormatFlags.Bottom)
  140. sf.LineAlignment = StringAlignment.Far;
  141. else if ((flags & TextFormatFlags.VerticalCenter) == TextFormatFlags.VerticalCenter)
  142. sf.LineAlignment = StringAlignment.Center;
  143. else
  144. sf.LineAlignment = StringAlignment.Near;
  145. // Ellipsis
  146. if ((flags & TextFormatFlags.EndEllipsis) == TextFormatFlags.EndEllipsis)
  147. sf.Trimming = StringTrimming.EllipsisCharacter;
  148. else if ((flags & TextFormatFlags.PathEllipsis) == TextFormatFlags.PathEllipsis)
  149. sf.Trimming = StringTrimming.EllipsisPath;
  150. else if ((flags & TextFormatFlags.WordEllipsis) == TextFormatFlags.WordEllipsis)
  151. sf.Trimming = StringTrimming.EllipsisWord;
  152. else
  153. sf.Trimming = StringTrimming.Character;
  154. // Hotkey Prefix
  155. if ((flags & TextFormatFlags.NoPrefix) == TextFormatFlags.NoPrefix)
  156. sf.HotkeyPrefix = HotkeyPrefix.None;
  157. else if ((flags & TextFormatFlags.HidePrefix) == TextFormatFlags.HidePrefix)
  158. sf.HotkeyPrefix = HotkeyPrefix.Hide;
  159. else
  160. sf.HotkeyPrefix = HotkeyPrefix.Show;
  161. // Text Padding
  162. if ((flags & TextFormatFlags.NoPadding) == TextFormatFlags.NoPadding)
  163. sf.FormatFlags |= StringFormatFlags.FitBlackBox;
  164. // Text Wrapping
  165. if ((flags & TextFormatFlags.SingleLine) == TextFormatFlags.SingleLine)
  166. sf.FormatFlags |= StringFormatFlags.NoWrap;
  167. else if ((flags & TextFormatFlags.TextBoxControl) == TextFormatFlags.TextBoxControl)
  168. sf.FormatFlags |= StringFormatFlags.LineLimit;
  169. // Other Flags
  170. if ((flags & TextFormatFlags.RightToLeft) == TextFormatFlags.RightToLeft)
  171. sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
  172. if ((flags & TextFormatFlags.NoClipping) == TextFormatFlags.NoClipping)
  173. sf.FormatFlags |= StringFormatFlags.NoClip;
  174. sf.FormatFlags |= StringFormatFlags.NoClip;
  175. return sf;
  176. }
  177. #endregion
  178. #region DllImports (Windows)
  179. [DllImport ("user32", CharSet = CharSet.Unicode)]
  180. static extern int DrawText (IntPtr hdc, string lpStr, int nCount, ref VisualStyles.UXTheme.RECT lpRect, int wFormat);
  181. [DllImport ("gdi32")]
  182. static extern int SetTextColor (IntPtr hdc, int crColor);
  183. [DllImport ("gdi32")]
  184. private extern static IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
  185. [DllImport ("gdi32")]
  186. static extern int SetBkColor (IntPtr hdc, int crColor);
  187. [DllImport ("gdi32")]
  188. static extern int SetBkMode (IntPtr hdc, int iBkMode);
  189. [DllImport ("gdi32")]
  190. static extern bool GetTextExtentExPoint (IntPtr hdc, string lpszStr, int cchString, int nMaxExtent, IntPtr lpnFit, IntPtr alpDx, out VisualStyles.UXTheme.SIZE lpSize);
  191. [DllImport ("gdi32")]
  192. static extern bool GetTextExtentPoint32 (IntPtr hdc, string lpString, int cbString, out VisualStyles.UXTheme.SIZE lpSize);
  193. #endregion
  194. }
  195. }
  196. #endif