2 // ToolStripRenderer.cs
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) Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
31 using System.ComponentModel;
33 using System.Drawing.Imaging;
34 using System.Drawing.Drawing2D;
36 namespace System.Windows.Forms
38 public abstract class ToolStripRenderer
40 private static ColorMatrix grayscale_matrix = new ColorMatrix (new float[][] {
41 //new float[]{0.3f,0.3f,0.3f,0,0},
42 //new float[]{0.59f,0.59f,0.59f,0,0},
43 //new float[]{0.11f,0.11f,0.11f,0,0},
44 //new float[]{0,0,0,1,0,0},
45 //new float[]{0,0,0,0,1,0},
46 //new float[]{0,0,0,0,0,1}
47 new float[]{0.2f,0.2f,0.2f,0,0},
48 new float[]{0.41f,0.41f,0.41f,0,0},
49 new float[]{0.11f,0.11f,0.11f,0,0},
50 new float[]{0.15f,0.15f,0.15f,1,0,0},
51 new float[]{0.15f,0.15f,0.15f,0,1,0},
52 new float[]{0.15f,0.15f,0.15f,0,0,1}
55 protected ToolStripRenderer ()
59 #region Public Methods
60 public static Image CreateDisabledImage(Image normalImage)
62 if (normalImage == null)
65 // Code adapted from ThemeWin32Classic.cs
66 ImageAttributes ia = new ImageAttributes();
67 ia.SetColorMatrix (grayscale_matrix);
69 Bitmap b = new Bitmap(normalImage);
70 Graphics.FromImage(b).DrawImage(normalImage, new Rectangle (0, 0, normalImage.Width, normalImage.Height), 0, 0, normalImage.Width, normalImage.Height, GraphicsUnit.Pixel, ia);
75 public void DrawArrow (ToolStripArrowRenderEventArgs e)
76 { this.OnRenderArrow (e); }
78 public void DrawButtonBackground (ToolStripItemRenderEventArgs e)
79 { this.OnRenderButtonBackground (e); }
81 public void DrawDropDownButtonBackground (ToolStripItemRenderEventArgs e)
82 { this.OnRenderDropDownButtonBackground (e); }
84 public void DrawGrip (ToolStripGripRenderEventArgs e)
85 { this.OnRenderGrip (e); }
87 public void DrawImageMargin (ToolStripRenderEventArgs e)
88 { this.OnRenderImageMargin (e); }
90 public void DrawItemBackground (ToolStripItemRenderEventArgs e)
91 { this.OnRenderItemBackground (e); }
93 public void DrawItemCheck (ToolStripItemImageRenderEventArgs e)
94 { this.OnRenderItemCheck (e); }
96 public void DrawItemImage (ToolStripItemImageRenderEventArgs e)
97 { this.OnRenderItemImage (e); }
99 public void DrawItemText (ToolStripItemTextRenderEventArgs e)
100 { this.OnRenderItemText (e); }
102 public void DrawLabelBackground (ToolStripItemRenderEventArgs e)
103 { this.OnRenderLabelBackground (e); }
105 public void DrawMenuItemBackground (ToolStripItemRenderEventArgs e)
106 { this.OnRenderMenuItemBackground (e); }
108 public void DrawOverflowButtonBackground (ToolStripItemRenderEventArgs e)
109 { this.OnRenderOverflowButtonBackground (e); }
111 public void DrawSeparator (ToolStripSeparatorRenderEventArgs e)
112 { this.OnRenderSeparator (e); }
114 public void DrawSplitButton (ToolStripItemRenderEventArgs e)
115 { this.OnRenderSplitButtonBackground (e); }
117 public void DrawStatusStripSizingGrip (ToolStripRenderEventArgs e)
118 { this.OnRenderStatusStripSizingGrip (e); }
120 public void DrawToolStripBackground (ToolStripRenderEventArgs e)
121 { this.OnRenderToolStripBackground (e); }
123 public void DrawToolStripBorder (ToolStripRenderEventArgs e)
124 { this.OnRenderToolStripBorder (e); }
126 public void DrawToolStripContentPanelBackground (ToolStripContentPanelRenderEventArgs e)
127 { this.OnRenderToolStripContentPanelBackground (e); }
129 public void DrawToolStripPanelBackground (ToolStripPanelRenderEventArgs e)
130 { this.OnRenderToolStripPanelBackground (e); }
132 public void DrawToolStripStatusLabelBackground (ToolStripItemRenderEventArgs e)
133 { this.OnRenderToolStripStatusLabelBackground (e); }
136 #region Protected Methods
137 protected internal virtual void Initialize (ToolStrip toolStrip) {}
138 protected internal virtual void InitializeContentPanel (ToolStripContentPanel contentPanel) {}
139 protected internal virtual void InitializeItem (ToolStripItem item) {}
140 protected internal virtual void InitializePanel (ToolStripPanel toolStripPanel) {}
142 protected virtual void OnRenderArrow (ToolStripArrowRenderEventArgs e)
144 switch (e.Direction) {
145 case ArrowDirection.Down:
146 using (Pen p = new Pen (e.ArrowColor)) {
147 int x = e.ArrowRectangle.Left + (e.ArrowRectangle.Width / 2) - 3;
148 int y = e.ArrowRectangle.Top + (e.ArrowRectangle.Height / 2) - 2;
150 DrawDownArrow (e.Graphics, p, x, y);
153 case ArrowDirection.Left:
155 case ArrowDirection.Right:
156 using (Pen p = new Pen (e.ArrowColor)) {
157 int x = e.ArrowRectangle.Left + (e.ArrowRectangle.Width / 2) - 3;
158 int y = e.ArrowRectangle.Top + (e.ArrowRectangle.Height / 2) - 4;
160 DrawRightArrow (e.Graphics, p, x, y);
163 case ArrowDirection.Up:
167 ToolStripArrowRenderEventHandler eh = (ToolStripArrowRenderEventHandler)Events[RenderArrowEvent];
172 protected virtual void OnRenderButtonBackground (ToolStripItemRenderEventArgs e)
174 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderButtonBackgroundEvent];
179 protected virtual void OnRenderDropDownButtonBackground (ToolStripItemRenderEventArgs e)
181 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderDropDownButtonBackgroundEvent];
186 protected virtual void OnRenderGrip (ToolStripGripRenderEventArgs e)
188 ToolStripGripRenderEventHandler eh = (ToolStripGripRenderEventHandler)Events [RenderGripEvent];
193 protected virtual void OnRenderImageMargin (ToolStripRenderEventArgs e)
195 ToolStripRenderEventHandler eh = (ToolStripRenderEventHandler)Events [RenderImageMarginEvent];
200 protected virtual void OnRenderItemBackground (ToolStripItemRenderEventArgs e)
202 if (e.Item.BackgroundImage != null) {
203 Rectangle item_bounds = new Rectangle (0, 0, e.Item.Width, e.Item.Height);
204 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (e.Item.BackColor), item_bounds);
205 DrawBackground (e.Graphics, item_bounds, e.Item.BackgroundImage, e.Item.BackgroundImageLayout);
208 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderItemBackgroundEvent];
213 protected virtual void OnRenderItemCheck (ToolStripItemImageRenderEventArgs e)
215 ToolStripItemImageRenderEventHandler eh = (ToolStripItemImageRenderEventHandler)Events [RenderItemCheckEvent];
220 protected virtual void OnRenderItemImage (ToolStripItemImageRenderEventArgs e)
222 bool need_dispose = false;
225 if (e.Item.RightToLeft == RightToLeft.Yes && e.Item.RightToLeftAutoMirrorImage == true) {
226 i = CreateMirrorImage (i);
230 if (e.Item.ImageTransparentColor != Color.Empty) {
231 ImageAttributes ia = new ImageAttributes ();
232 ia.SetColorKey (e.Item.ImageTransparentColor, e.Item.ImageTransparentColor);
233 e.Graphics.DrawImage (i, e.ImageRectangle, 0, 0, i.Width, i.Height, GraphicsUnit.Pixel, ia);
237 e.Graphics.DrawImage (i, e.ImageRectangle);
242 ToolStripItemImageRenderEventHandler eh = (ToolStripItemImageRenderEventHandler)Events [RenderItemImageEvent];
247 protected virtual void OnRenderItemText (ToolStripItemTextRenderEventArgs e)
249 if (e.TextDirection == ToolStripTextDirection.Vertical90) {
250 GraphicsState gs = e.Graphics.Save ();
251 PointF p = new PointF (e.Graphics.Transform.OffsetX, e.Graphics.Transform.OffsetY);
253 e.Graphics.ResetTransform ();
254 e.Graphics.RotateTransform (90);
256 RectangleF r = new RectangleF ((e.Item.Height - e.TextRectangle.Height) / 2, (e.TextRectangle.Width + p.X) * -1 - 18, e.TextRectangle.Height, e.TextRectangle.Width);
258 StringFormat sf = new StringFormat ();
259 sf.Alignment = StringAlignment.Center;
261 e.Graphics.DrawString (e.Text, e.TextFont, ThemeEngine.Current.ResPool.GetSolidBrush (e.TextColor), r, sf);
263 e.Graphics.Restore (gs);
264 } else if (e.TextDirection == ToolStripTextDirection.Vertical270) {
265 GraphicsState gs = e.Graphics.Save ();
266 PointF p = new PointF (e.Graphics.Transform.OffsetX, e.Graphics.Transform.OffsetY);
268 e.Graphics.ResetTransform ();
269 e.Graphics.RotateTransform (270);
271 RectangleF r = new RectangleF (-e.TextRectangle.Height - (e.Item.Height - e.TextRectangle.Height) / 2, (e.TextRectangle.Width + p.X) + 4, e.TextRectangle.Height, e.TextRectangle.Width);
273 StringFormat sf = new StringFormat ();
274 sf.Alignment = StringAlignment.Center;
276 e.Graphics.DrawString (e.Text, e.TextFont, ThemeEngine.Current.ResPool.GetSolidBrush (e.TextColor), r, sf);
278 e.Graphics.Restore (gs);
280 TextRenderer.DrawText (e.Graphics, e.Text, e.TextFont, e.TextRectangle, e.TextColor, e.TextFormat);
282 ToolStripItemTextRenderEventHandler eh = (ToolStripItemTextRenderEventHandler)Events[RenderItemTextEvent];
287 protected virtual void OnRenderLabelBackground (ToolStripItemRenderEventArgs e)
289 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderLabelBackgroundEvent];
294 protected virtual void OnRenderMenuItemBackground (ToolStripItemRenderEventArgs e)
296 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderMenuItemBackgroundEvent];
301 protected virtual void OnRenderOverflowButtonBackground (ToolStripItemRenderEventArgs e)
303 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderOverflowButtonBackgroundEvent];
308 protected virtual void OnRenderSeparator (ToolStripSeparatorRenderEventArgs e)
310 ToolStripSeparatorRenderEventHandler eh = (ToolStripSeparatorRenderEventHandler)Events [RenderSeparatorEvent];
315 protected virtual void OnRenderSplitButtonBackground (ToolStripItemRenderEventArgs e)
317 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderSplitButtonBackgroundEvent];
322 protected virtual void OnRenderStatusStripSizingGrip (ToolStripRenderEventArgs e)
324 StatusStrip ss = (StatusStrip)e.ToolStrip;
326 if (ss.SizingGrip == true)
327 DrawSizingGrip (e.Graphics, ss.SizeGripBounds);
329 ToolStripRenderEventHandler eh = (ToolStripRenderEventHandler)Events [RenderStatusStripSizingGripEvent];
334 protected virtual void OnRenderToolStripBackground (ToolStripRenderEventArgs e)
336 ToolStripRenderEventHandler eh = (ToolStripRenderEventHandler)Events [RenderToolStripBackgroundEvent];
341 protected virtual void OnRenderToolStripBorder (ToolStripRenderEventArgs e)
343 ToolStripRenderEventHandler eh = (ToolStripRenderEventHandler)Events [RenderToolStripBorderEvent];
348 protected virtual void OnRenderToolStripContentPanelBackground (ToolStripContentPanelRenderEventArgs e)
350 ToolStripContentPanelRenderEventHandler eh = (ToolStripContentPanelRenderEventHandler)Events [RenderToolStripContentPanelBackgroundEvent];
355 protected virtual void OnRenderToolStripPanelBackground (ToolStripPanelRenderEventArgs e)
357 ToolStripPanelRenderEventHandler eh = (ToolStripPanelRenderEventHandler)Events [RenderToolStripPanelBackgroundEvent];
362 protected virtual void OnRenderToolStripStatusLabelBackground (ToolStripItemRenderEventArgs e)
364 ToolStripItemRenderEventHandler eh = (ToolStripItemRenderEventHandler)Events [RenderToolStripStatusLabelBackgroundEvent];
370 #region Public Events
371 EventHandlerList events;
373 EventHandlerList Events {
376 events = new EventHandlerList ();
381 static object RenderArrowEvent = new object ();
382 static object RenderButtonBackgroundEvent = new object ();
383 static object RenderDropDownButtonBackgroundEvent = new object ();
384 static object RenderGripEvent = new object ();
385 static object RenderImageMarginEvent = new object ();
386 static object RenderItemBackgroundEvent = new object ();
387 static object RenderItemCheckEvent = new object ();
388 static object RenderItemImageEvent = new object ();
389 static object RenderItemTextEvent = new object ();
390 static object RenderLabelBackgroundEvent = new object ();
391 static object RenderMenuItemBackgroundEvent = new object ();
392 static object RenderOverflowButtonBackgroundEvent = new object ();
393 static object RenderSeparatorEvent = new object ();
394 static object RenderSplitButtonBackgroundEvent = new object ();
395 static object RenderStatusStripSizingGripEvent = new object ();
396 static object RenderToolStripBackgroundEvent = new object ();
397 static object RenderToolStripBorderEvent = new object ();
398 static object RenderToolStripContentPanelBackgroundEvent = new object ();
399 static object RenderToolStripPanelBackgroundEvent = new object ();
400 static object RenderToolStripStatusLabelBackgroundEvent = new object ();
402 public event ToolStripArrowRenderEventHandler RenderArrow {
403 add { Events.AddHandler (RenderArrowEvent, value); }
404 remove {Events.RemoveHandler (RenderArrowEvent, value); }
406 public event ToolStripItemRenderEventHandler RenderButtonBackground {
407 add { Events.AddHandler (RenderButtonBackgroundEvent, value); }
408 remove {Events.RemoveHandler (RenderButtonBackgroundEvent, value); }
410 public event ToolStripItemRenderEventHandler RenderDropDownButtonBackground {
411 add { Events.AddHandler (RenderDropDownButtonBackgroundEvent, value); }
412 remove {Events.RemoveHandler (RenderDropDownButtonBackgroundEvent, value); }
414 public event ToolStripGripRenderEventHandler RenderGrip {
415 add { Events.AddHandler (RenderGripEvent, value); }
416 remove {Events.RemoveHandler (RenderGripEvent, value); }
418 public event ToolStripRenderEventHandler RenderImageMargin {
419 add { Events.AddHandler (RenderImageMarginEvent, value); }
420 remove {Events.RemoveHandler (RenderImageMarginEvent, value); }
422 public event ToolStripItemRenderEventHandler RenderItemBackground {
423 add { Events.AddHandler (RenderItemBackgroundEvent, value); }
424 remove {Events.RemoveHandler (RenderItemBackgroundEvent, value); }
426 public event ToolStripItemImageRenderEventHandler RenderItemCheck {
427 add { Events.AddHandler (RenderItemCheckEvent, value); }
428 remove {Events.RemoveHandler (RenderItemCheckEvent, value); }
430 public event ToolStripItemImageRenderEventHandler RenderItemImage {
431 add { Events.AddHandler (RenderItemImageEvent, value); }
432 remove {Events.RemoveHandler (RenderItemImageEvent, value); }
434 public event ToolStripItemTextRenderEventHandler RenderItemText {
435 add { Events.AddHandler (RenderItemTextEvent, value); }
436 remove {Events.RemoveHandler (RenderItemTextEvent, value); }
438 public event ToolStripItemRenderEventHandler RenderLabelBackground {
439 add { Events.AddHandler (RenderLabelBackgroundEvent, value); }
440 remove {Events.RemoveHandler (RenderLabelBackgroundEvent, value); }
442 public event ToolStripItemRenderEventHandler RenderMenuItemBackground {
443 add { Events.AddHandler (RenderMenuItemBackgroundEvent, value); }
444 remove {Events.RemoveHandler (RenderMenuItemBackgroundEvent, value); }
446 public event ToolStripItemRenderEventHandler RenderOverflowButtonBackground {
447 add { Events.AddHandler (RenderOverflowButtonBackgroundEvent, value); }
448 remove {Events.RemoveHandler (RenderOverflowButtonBackgroundEvent, value); }
450 public event ToolStripSeparatorRenderEventHandler RenderSeparator {
451 add { Events.AddHandler (RenderSeparatorEvent, value); }
452 remove {Events.RemoveHandler (RenderSeparatorEvent, value); }
454 public event ToolStripItemRenderEventHandler RenderSplitButtonBackground {
455 add { Events.AddHandler (RenderSplitButtonBackgroundEvent, value); }
456 remove {Events.RemoveHandler (RenderSplitButtonBackgroundEvent, value); }
458 public event ToolStripRenderEventHandler RenderStatusStripSizingGrip {
459 add { Events.AddHandler (RenderStatusStripSizingGripEvent, value); }
460 remove {Events.RemoveHandler (RenderStatusStripSizingGripEvent, value); }
462 public event ToolStripRenderEventHandler RenderToolStripBackground {
463 add { Events.AddHandler (RenderToolStripBackgroundEvent, value); }
464 remove {Events.RemoveHandler (RenderToolStripBackgroundEvent, value); }
466 public event ToolStripRenderEventHandler RenderToolStripBorder {
467 add { Events.AddHandler (RenderToolStripBorderEvent, value); }
468 remove {Events.RemoveHandler (RenderToolStripBorderEvent, value); }
470 public event ToolStripContentPanelRenderEventHandler RenderToolStripContentPanelBackground {
471 add { Events.AddHandler (RenderToolStripContentPanelBackgroundEvent, value); }
472 remove {Events.RemoveHandler (RenderToolStripContentPanelBackgroundEvent, value); }
474 public event ToolStripPanelRenderEventHandler RenderToolStripPanelBackground {
475 add { Events.AddHandler (RenderToolStripPanelBackgroundEvent, value); }
476 remove {Events.RemoveHandler (RenderToolStripPanelBackgroundEvent, value); }
478 public event ToolStripItemRenderEventHandler RenderToolStripStatusLabelBackground {
479 add { Events.AddHandler (RenderToolStripStatusLabelBackgroundEvent, value); }
480 remove {Events.RemoveHandler (RenderToolStripStatusLabelBackgroundEvent, value); }
484 #region Private Methods
485 internal static Image CreateMirrorImage (Image normalImage)
487 if (normalImage == null)
490 Bitmap b = new Bitmap (normalImage);
491 b.RotateFlip (RotateFlipType.RotateNoneFlipX);
496 private void DrawBackground (Graphics g, Rectangle bounds, Image image, ImageLayout layout)
498 // Center and Tile don't matter if the image is larger than the control
499 if (layout == ImageLayout.Center || layout == ImageLayout.Tile)
500 if (image.Size.Width >= bounds.Size.Width && image.Size.Height >= bounds.Size.Height)
501 layout = ImageLayout.None;
504 case ImageLayout.None:
505 g.DrawImageUnscaledAndClipped (image, bounds);
507 case ImageLayout.Tile:
511 while (y < bounds.Height) {
512 while (x < bounds.Width) {
513 g.DrawImageUnscaledAndClipped (image, bounds);
520 case ImageLayout.Center:
521 Rectangle r = new Rectangle ((bounds.Size.Width - image.Size.Width) / 2, (bounds.Size.Height - image.Size.Height) / 2, image.Width, image.Height);
522 g.DrawImageUnscaledAndClipped (image, r);
524 case ImageLayout.Stretch:
525 g.DrawImage (image, bounds);
527 case ImageLayout.Zoom:
528 if (((float)image.Height / (float)image.Width) < ((float)bounds.Height / (float)bounds.Width)) {
529 Rectangle rzoom = new Rectangle (0, 0, bounds.Width, (int)((float)bounds.Width * ((float)image.Height / (float)image.Width)));
530 rzoom.Y = (bounds.Height - rzoom.Height)/ 2;
531 g.DrawImage (image, rzoom);
533 Rectangle rzoom = new Rectangle (0, 0, (int)((float)bounds.Height * ((float)image.Width / (float)image.Height)), bounds.Height);
534 rzoom.X = (bounds.Width - rzoom.Width) / 2;
535 g.DrawImage (image, rzoom);
541 internal static void DrawRightArrow (Graphics g, Pen p, int x, int y)
543 g.DrawLine (p, x, y, x, y + 6);
544 g.DrawLine (p, x + 1, y + 1, x + 1, y + 5);
545 g.DrawLine (p, x + 2, y + 2, x + 2, y + 4);
546 g.DrawLine (p, x + 2, y + 3, x + 3, y + 3);
549 internal static void DrawDownArrow (Graphics g, Pen p, int x, int y)
551 g.DrawLine (p, x + 1, y, x + 5, y);
552 g.DrawLine (p, x + 2, y + 1, x + 4, y + 1);
553 g.DrawLine (p, x + 3, y + 1, x + 3, y + 2);
556 private void DrawSizingGrip (Graphics g, Rectangle rect)
558 DrawGripBox (g, rect.Right - 5, rect.Bottom - 5);
559 DrawGripBox (g, rect.Right - 9, rect.Bottom - 5);
560 DrawGripBox (g, rect.Right - 5, rect.Bottom - 9);
561 DrawGripBox (g, rect.Right - 13, rect.Bottom - 5);
562 DrawGripBox (g, rect.Right - 5, rect.Bottom - 13);
563 DrawGripBox (g, rect.Right - 9, rect.Bottom - 9);
566 private void DrawGripBox (Graphics g, int x, int y)
568 g.DrawRectangle (Pens.White, x + 1, y + 1, 1, 1);
569 g.DrawRectangle (ThemeEngine.Current.ResPool.GetPen (Color.FromArgb (172, 168, 153)), x, y, 1, 1);