2006-08-04 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / TextRenderer.cs
1 //\r
2 // TextRenderer.cs\r
3 //\r
4 // Permission is hereby granted, free of charge, to any person obtaining\r
5 // a copy of this software and associated documentation files (the\r
6 // "Software"), to deal in the Software without restriction, including\r
7 // without limitation the rights to use, copy, modify, merge, publish,\r
8 // distribute, sublicense, and/or sell copies of the Software, and to\r
9 // permit persons to whom the Software is furnished to do so, subject to\r
10 // the following conditions:\r
11 // \r
12 // The above copyright notice and this permission notice shall be\r
13 // included in all copies or substantial portions of the Software.\r
14 // \r
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22 //\r
23 // Copyright (c) 2006 Novell, Inc.\r
24 //\r
25 // Authors:\r
26 //      Jonathan Pobst (monkey@jpobst.com)\r
27 //\r
28 \r
29 #if NET_2_0\r
30 using System.Drawing;\r
31 using System.Runtime.InteropServices;\r
32 using System.Text;\r
33 using System.Drawing.Text;\r
34 \r
35 namespace System.Windows.Forms\r
36 {\r
37         public sealed class TextRenderer\r
38         {\r
39                 #region Public Methods\r
40                 [MonoTODO("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]\r
41                 public static void DrawText (IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags)\r
42                 {\r
43                         if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {\r
44                                 IntPtr hdc = dc.GetHdc ();\r
45 \r
46                                 SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));\r
47                                 SetBkMode (hdc, 1);     //1-Transparent, 2-Opaque\r
48 \r
49                                 VisualStyles.UXTheme.RECT r = VisualStyles.UXTheme.RECT.FromRectangle (bounds);\r
50 \r
51                                 if (font != null)\r
52                                         SelectObject (hdc, font.ToHfont ());\r
53 \r
54                                 DrawText (hdc, text, text.Length, ref r, (int)flags);\r
55                                 dc.ReleaseHdc ();\r
56                         }\r
57                         else {\r
58                                 Graphics g;\r
59 \r
60                                 if (dc is Graphics)\r
61                                         g = (Graphics)dc;\r
62                                 else\r
63                                         g = Graphics.FromHdc (dc.GetHdc ());\r
64 \r
65                                 StringFormat sf = FlagsToStringFormat (flags);\r
66 \r
67                                 using (Brush b = new SolidBrush (foreColor))\r
68                                         g.DrawString (text, font, b, bounds, sf);\r
69 \r
70                                 if (!(dc is Graphics)) {\r
71                                         g.Dispose ();\r
72                                         dc.ReleaseHdc ();\r
73                                 }\r
74                         }\r
75                 }\r
76 \r
77                 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]\r
78                 public static void DrawText (IDeviceContext dc, string text, Font font, Point pt, Color foreColor, TextFormatFlags flags)\r
79                 {\r
80                         if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {\r
81                                 IntPtr hdc = dc.GetHdc ();\r
82 \r
83                                 SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));\r
84                                 SetBkMode (hdc, 1);     //1-Transparent, 2-Opaque\r
85 \r
86                                 Size sz = MeasureText(text, font);\r
87                                 \r
88                                 VisualStyles.UXTheme.RECT r = new System.Windows.Forms.VisualStyles.UXTheme.RECT(pt.X, pt.Y, pt.X + sz.Width, pt.Y + sz.Height);\r
89 \r
90                                 if (font != null)\r
91                                         SelectObject (hdc, font.ToHfont ());\r
92 \r
93                                 DrawText (hdc, text, text.Length, ref r, (int)flags);\r
94                                 dc.ReleaseHdc ();\r
95                         }\r
96                         else {\r
97                                 Graphics g;\r
98 \r
99                                 if (dc is Graphics)\r
100                                         g = (Graphics)dc;\r
101                                 else\r
102                                         g = Graphics.FromHdc (dc.GetHdc ());\r
103 \r
104                                 StringFormat sf = FlagsToStringFormat (flags);\r
105 \r
106                                 using (Brush b = new SolidBrush (foreColor))\r
107                                         g.DrawString (text, font, b, pt, sf);\r
108 \r
109                                 if (!(dc is Graphics)) {\r
110                                         g.Dispose ();\r
111                                         dc.ReleaseHdc ();\r
112                                 }\r
113                         }\r
114                 }\r
115 \r
116                 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]\r
117                 public static Size MeasureText (string text, Font font)\r
118                 {\r
119                         if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {\r
120                                 Bitmap b = new Bitmap (5, 5);\r
121                                 Graphics g = Graphics.FromImage (b);\r
122                                 \r
123                                 IntPtr hdc = g.GetHdc ();\r
124 \r
125                                 if (font != null)\r
126                                         SelectObject (hdc, font.ToHfont ());\r
127                                         \r
128                                 VisualStyles.UXTheme.SIZE text_size = new System.Windows.Forms.VisualStyles.UXTheme.SIZE();\r
129 \r
130                                 GetTextExtentPoint32 (hdc, text, text.Length, out text_size);\r
131                                 \r
132                                 g.ReleaseHdc();\r
133                                 \r
134                                 return text_size.ToSize();\r
135                         }\r
136                         else {\r
137                         Bitmap b = new Bitmap (5, 5);\r
138                         Graphics g = Graphics.FromImage (b);\r
139 \r
140                         return g.MeasureString(text,font).ToSize();                     \r
141                         }\r
142                 }\r
143                 #endregion\r
144 \r
145                 #region Private Methods\r
146                 private static StringFormat FlagsToStringFormat (TextFormatFlags flags)\r
147                 {\r
148                         StringFormat sf = new StringFormat ();\r
149 \r
150                         // Translation table: http://msdn.microsoft.com/msdnmag/issues/06/03/TextRendering/default.aspx?fig=true#fig4\r
151 \r
152                         // Horizontal Alignment\r
153                         if ((flags & TextFormatFlags.HorizontalCenter) == TextFormatFlags.HorizontalCenter)\r
154                                 sf.Alignment = StringAlignment.Center;\r
155                         else if ((flags & TextFormatFlags.Right) == TextFormatFlags.Right)\r
156                                 sf.Alignment = StringAlignment.Far;\r
157                         else\r
158                                 sf.Alignment = StringAlignment.Near;\r
159 \r
160                         // Vertical Alignment\r
161                         if ((flags & TextFormatFlags.Bottom) == TextFormatFlags.Bottom)\r
162                                 sf.LineAlignment = StringAlignment.Far;\r
163                         else if ((flags & TextFormatFlags.VerticalCenter) == TextFormatFlags.VerticalCenter)\r
164                                 sf.LineAlignment = StringAlignment.Center;\r
165                         else\r
166                                 sf.LineAlignment = StringAlignment.Near;\r
167 \r
168                         // Ellipsis\r
169                         if ((flags & TextFormatFlags.EndEllipsis) == TextFormatFlags.EndEllipsis)\r
170                                 sf.Trimming = StringTrimming.EllipsisCharacter;\r
171                         else if ((flags & TextFormatFlags.PathEllipsis) == TextFormatFlags.PathEllipsis)\r
172                                 sf.Trimming = StringTrimming.EllipsisPath;\r
173                         else if ((flags & TextFormatFlags.WordEllipsis) == TextFormatFlags.WordEllipsis)\r
174                                 sf.Trimming = StringTrimming.EllipsisWord;\r
175                         else\r
176                                 sf.Trimming = StringTrimming.Character;\r
177 \r
178                         // Hotkey Prefix\r
179                         if ((flags & TextFormatFlags.NoPrefix) == TextFormatFlags.NoPrefix)\r
180                                 sf.HotkeyPrefix = HotkeyPrefix.None;\r
181                         else if ((flags & TextFormatFlags.HidePrefix) == TextFormatFlags.HidePrefix)\r
182                                 sf.HotkeyPrefix = HotkeyPrefix.Hide;\r
183                         else\r
184                                 sf.HotkeyPrefix = HotkeyPrefix.Show;\r
185 \r
186                         // Text Padding\r
187                         if ((flags & TextFormatFlags.NoPadding) == TextFormatFlags.NoPadding)\r
188                                 sf.FormatFlags |= StringFormatFlags.FitBlackBox;\r
189 \r
190                         // Text Wrapping\r
191                         if ((flags & TextFormatFlags.SingleLine) == TextFormatFlags.SingleLine)\r
192                                 sf.FormatFlags |= StringFormatFlags.NoWrap;\r
193                         else if ((flags & TextFormatFlags.TextBoxControl) == TextFormatFlags.TextBoxControl)\r
194                                 sf.FormatFlags |= StringFormatFlags.LineLimit;\r
195 \r
196                         // Other Flags\r
197                         if ((flags & TextFormatFlags.RightToLeft) == TextFormatFlags.RightToLeft)\r
198                                 sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;\r
199                         if ((flags & TextFormatFlags.NoClipping) == TextFormatFlags.NoClipping)\r
200                                 sf.FormatFlags |= StringFormatFlags.NoClip;\r
201                         sf.FormatFlags |= StringFormatFlags.NoClip;\r
202 \r
203                         return sf;\r
204                 }\r
205                 #endregion\r
206 \r
207                 #region DllImports (Windows)\r
208                 [DllImport ("user32", CharSet = CharSet.Unicode)]\r
209                 static extern int DrawText (IntPtr hdc, string lpStr, int nCount, ref VisualStyles.UXTheme.RECT lpRect, int wFormat);\r
210 \r
211                 [DllImport ("gdi32")]\r
212                 static extern int SetTextColor (IntPtr hdc, int crColor);\r
213 \r
214                 [DllImport ("gdi32")]\r
215                 private extern static IntPtr SelectObject (IntPtr hDC, IntPtr hObject);\r
216 \r
217                 [DllImport ("gdi32")]\r
218                 static extern int SetBkColor (IntPtr hdc, int crColor);\r
219 \r
220                 [DllImport ("gdi32")]\r
221                 static extern int SetBkMode (IntPtr hdc, int iBkMode);\r
222 \r
223                 [DllImport ("gdi32")]\r
224                 static extern bool GetTextExtentExPoint (IntPtr hdc, string lpszStr, int cchString, int nMaxExtent, IntPtr lpnFit, IntPtr alpDx, out VisualStyles.UXTheme.SIZE lpSize);\r
225 \r
226                 [DllImport ("gdi32")]\r
227                 static extern bool GetTextExtentPoint32 (IntPtr hdc, string lpString, int cbString, out VisualStyles.UXTheme.SIZE lpSize);\r
228                 #endregion\r
229         }\r
230 \r
231 }\r
232 #endif