File: winforms\Managed\System\WinForms\ToolStripHighContrastRenderer.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
#region Using directives
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Collections.Specialized;
 
 
#endregion
 
namespace System.Windows.Forms {
 
	// this renderer supports high contrast for ToolStripProfessional and ToolStripSystemRenderer.
	internal class ToolStripHighContrastRenderer : ToolStripSystemRenderer {
 
		private const int GRIP_PADDING = 4;
 
		BitVector32 options = new BitVector32();
		private static readonly int optionsDottedBorder = BitVector32.CreateMask();
		private static readonly int optionsDottedGrip = BitVector32.CreateMask(optionsDottedBorder);
		private static readonly int optionsFillWhenSelected = BitVector32.CreateMask(optionsDottedGrip);
 
		public ToolStripHighContrastRenderer(bool systemRenderMode) {
			options[optionsDottedBorder | optionsDottedGrip | optionsFillWhenSelected] = !systemRenderMode;
		}
		
		public bool DottedBorder {
			get { return options[optionsDottedBorder]; }
		}
		public bool DottedGrip {
			get { return options[optionsDottedGrip]; }
		}
		public bool FillWhenSelected{
			get { return options[optionsFillWhenSelected]; }
		}
 
        // this is a renderer override, so return null so we dont get into an infinite loop.
        internal override ToolStripRenderer RendererOverride {
            get { return null; }
        }
        
        protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) {
            base.OnRenderArrow(e);
        }
 
		protected override void OnRenderGrip(ToolStripGripRenderEventArgs e) {
 
			if (DottedGrip) {
				Graphics g = e.Graphics;
				Rectangle bounds = e.GripBounds;
				ToolStrip toolStrip = e.ToolStrip;
 
				int height = (toolStrip.Orientation == Orientation.Horizontal) ? bounds.Height : bounds.Width;
				int width = (toolStrip.Orientation == Orientation.Horizontal) ? bounds.Width : bounds.Height;
 
				int numRectangles = (height - (GRIP_PADDING * 2)) / 4;
 
				if (numRectangles > 0) {
					Rectangle[] shadowRects = new Rectangle[numRectangles];
					int startY = GRIP_PADDING;
					int startX = (width / 2);
 
					for (int i = 0; i < numRectangles; i++) {
						shadowRects[i] = (toolStrip.Orientation == Orientation.Horizontal) ?
											new Rectangle(startX, startY, 2, 2) :
											new Rectangle(startY, startX, 2, 2);
 
						startY += 4;
					}
 
					g.FillRectangles(SystemBrushes.ControlLight, shadowRects);
 
 
 
				}
			}
			else {
				base.OnRenderGrip(e);
			}
		}
 
	
		protected override void OnRenderDropDownButtonBackground(ToolStripItemRenderEventArgs e) {
			
			if (FillWhenSelected) {
				RenderItemInternalFilled(e, false);
			}
			else {
				base.OnRenderDropDownButtonBackground(e);
				if (e.Item.Pressed) {
					e.Graphics.DrawRectangle(SystemPens.ButtonHighlight, new Rectangle(0, 0, e.Item.Width - 1, e.Item.Height - 1));
				}
			}
			
		}
 
		protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) {
            if (AccessibilityImprovements.Level1) {
                // The ARGB values came directly from the bitmap. (See
                // NetFXDev1\src\NDP\fx\src\Microsoft\Managed\Resources\System\Microsoft\checked.bmp).
                // If the bitmap colors change this code will no longer work and will
                // need to be updated.
                Color checkColor = Color.FromArgb(255, 4, 2, 4);
 
                // Create a color map to remap the check color to either the theme
                // color for highlighted text or menu text, depending on whether
                // the menu item is selected.
                ColorMap[] checkColorMap = new ColorMap[1];
                checkColorMap[0] = new ColorMap();
                checkColorMap[0].OldColor = checkColor;
 
                checkColorMap[0].NewColor = ((e.Item.Selected || e.Item.Pressed) && e.Item.Enabled) ?
                    SystemColors.HighlightText : SystemColors.MenuText;
 
                // If we already have an image attributes associated with the event,
                // just add the color map. Otherwise, create a new one.
                ImageAttributes imageAttr = e.ImageAttributes ?? new ImageAttributes();
                imageAttr.SetRemapTable(checkColorMap, ColorAdjustType.Bitmap);
                e.ImageAttributes = imageAttr;
            }
 
            base.OnRenderItemCheck(e);
		}
	
		protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) {
			// do nothing 
		}
		protected override void OnRenderItemBackground(ToolStripItemRenderEventArgs e) {
			base.OnRenderItemBackground(e);
		}
 
        protected override void OnRenderSplitButtonBackground(ToolStripItemRenderEventArgs e) {
			ToolStripSplitButton item = e.Item as ToolStripSplitButton;
			Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
			Graphics g = e.Graphics;
 
			if (item != null) {
				Rectangle dropDownRect = item.DropDownButtonBounds;
 
				if (item.Pressed) {
					g.DrawRectangle(SystemPens.ButtonHighlight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
					
				}
				else if (item.Selected) {
					g.FillRectangle(SystemBrushes.Highlight, bounds);
					g.DrawRectangle(SystemPens.ButtonHighlight, bounds.X, bounds.Y, bounds.Width-1, bounds.Height -1);
					g.DrawRectangle(SystemPens.ButtonHighlight, dropDownRect);
				}
 
				Color arrowColor = AccessibilityImprovements.Level2 && item.Selected && !item.Pressed ? SystemColors.HighlightText : SystemColors.ControlText;
				DrawArrow(new ToolStripArrowRenderEventArgs(g, item, dropDownRect, arrowColor, ArrowDirection.Down));
			}
		}
        
		protected override void OnRenderStatusStripSizingGrip(ToolStripRenderEventArgs e) {
			base.OnRenderStatusStripSizingGrip(e);
		}
 
		protected override void OnRenderLabelBackground(ToolStripItemRenderEventArgs e) {
			if (FillWhenSelected) {
				RenderItemInternalFilled(e);
			}
			else {
				base.OnRenderLabelBackground(e);
			}
		}
		protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) {
		
			base.OnRenderMenuItemBackground(e);
			if (!e.Item.IsOnDropDown && e.Item.Pressed) {
				e.Graphics.DrawRectangle(SystemPens.ButtonHighlight, 0, 0, e.Item.Width - 1, e.Item.Height - 1);
			}
		}
		protected override void OnRenderOverflowButtonBackground(ToolStripItemRenderEventArgs e) {
			if (FillWhenSelected) {
 
				RenderItemInternalFilled(e, /*pressFill = */false);
				ToolStripItem item = e.Item;
				Graphics g = e.Graphics;
				Color arrowColor = item.Enabled ? SystemColors.ControlText : SystemColors.ControlDark;
				DrawArrow(new ToolStripArrowRenderEventArgs(g, item, new Rectangle(Point.Empty, item.Size), arrowColor, ArrowDirection.Down));
			
		
			}
			else {
				base.OnRenderOverflowButtonBackground(e);		
			}
		}
 
        protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) {
 
            if (AccessibilityImprovements.Level2 && e.Item.Selected && (!e.Item.Pressed || e.Item is ToolStripButton)) {
                e.DefaultTextColor = SystemColors.HighlightText;
            }
            else if (e.TextColor != SystemColors.HighlightText && e.TextColor != SystemColors.ControlText) {
                // we'll change the DefaultTextColor, if someone wants to change this,manually set the TextColor property.
                if (e.Item.Selected || e.Item.Pressed) {
                    e.DefaultTextColor = SystemColors.HighlightText;
                }
                else {
                    e.DefaultTextColor = SystemColors.ControlText;
                }
            }
 
 
            // VSO-399067 ToolstripButtons that are checked are rendered with a highlight
            // background. In that case, set the text color to highlight as well.
            if (AccessibilityImprovements.Level1 &&
                typeof(ToolStripButton).IsAssignableFrom(e.Item.GetType()) &&
                ((ToolStripButton)e.Item).DisplayStyle != ToolStripItemDisplayStyle.Image &&
                ((ToolStripButton)e.Item).Checked) {
                e.TextColor = SystemColors.HighlightText;
            }
                
            base.OnRenderItemText(e);
        }
 
        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) {
            // do nothing. LOGO requirements ask us not to paint background effects behind
        }
 
		protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) {
			Rectangle bounds = new Rectangle(Point.Empty, e.ToolStrip.Size);
			Graphics g = e.Graphics;
 
 
			if (e.ToolStrip is ToolStripDropDown) {
 
				g.DrawRectangle(SystemPens.ButtonHighlight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
 
				if (!(e.ToolStrip is ToolStripOverflow)) {
					// make the neck connected.
					g.FillRectangle(SystemBrushes.Control, e.ConnectedArea);
				
				}
			}
			else if (e.ToolStrip is MenuStrip) {
				// do nothing
			}
			else if (e.ToolStrip is StatusStrip) {
				g.DrawRectangle(SystemPens.ButtonShadow, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
 
			}
			else {
				RenderToolStripBackgroundInternal(e);
			}
		}
 
		private void RenderToolStripBackgroundInternal(ToolStripRenderEventArgs e) {
			Rectangle bounds = new Rectangle(Point.Empty, e.ToolStrip.Size);
			Graphics g = e.Graphics;
 
			if (DottedBorder) {
 
					using (Pen p = new Pen(SystemColors.ButtonShadow)) {
						p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
 
						bool oddWidth = ((bounds.Width & 0x1) == 0x1);
						bool oddHeight = ((bounds.Height & 0x1) == 0x1);
						int indent = 2;
 
						// top
						g.DrawLine(p, bounds.X + indent, bounds.Y, bounds.Width - 1, bounds.Y);
						// bottom
						g.DrawLine(p, bounds.X + indent, bounds.Height - 1, bounds.Width - 1, bounds.Height - 1);
 
						// left
						g.DrawLine(p, bounds.X, bounds.Y + indent, bounds.X, bounds.Height - 1);
						// right
						g.DrawLine(p, bounds.Width - 1, bounds.Y + indent, bounds.Width - 1, bounds.Height - 1);
 
						// connecting pixels
 
						// top left conntecting pixel - always drawn
						g.FillRectangle(SystemBrushes.ButtonShadow, new Rectangle(1, 1, 1, 1));
 
						if (oddWidth) {
							// top right pixel
							g.FillRectangle(SystemBrushes.ButtonShadow, new Rectangle(bounds.Width - 2, 1, 1, 1));
						}
						// bottom conntecting pixels - drawn only if height is odd
						if (oddHeight) {
							// bottom left
							g.FillRectangle(SystemBrushes.ButtonShadow, new Rectangle(1, bounds.Height - 2, 1, 1));
 
						}
 
						// top and bottom right conntecting pixel - drawn only if height and width are odd
						if (oddHeight && oddWidth) {
							// bottom right
							g.FillRectangle(SystemBrushes.ButtonShadow, new Rectangle(bounds.Width - 2, bounds.Height - 2, 1, 1));
						}
 
					}
				}
				else {
					// draw solid border
					bounds.Width -= 1;
					bounds.Height -= 1;
					g.DrawRectangle(SystemPens.ButtonShadow, bounds);
				}
			
		}
		protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) {
 
			Pen foreColorPen = SystemPens.ButtonShadow;
 
			Graphics g = e.Graphics;
			Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
			
 
			if (e.Vertical) {
				if (bounds.Height >= 8) {
					bounds.Inflate(0, -4);     // scoot down 4PX and start drawing
				}
				// Draw dark line
				int startX = bounds.Width / 2;
 
				g.DrawLine(foreColorPen, startX, bounds.Top, startX, bounds.Bottom - 1);
		
			}
			else {
				//
				// horizontal separator
				if (bounds.Width >= 4) {
					bounds.Inflate(-2, 0);        // scoot over 2PX and start drawing
				}
 
				// Draw dark line
				int startY = bounds.Height / 2;
 
				g.DrawLine(foreColorPen, bounds.Left, startY, bounds.Right - 1, startY);
 
			}
			
		}
 
		// Indicates whether system is currently set to high contrast 'white on black' mode
		internal static bool IsHighContrastWhiteOnBlack()
		{
			return SystemColors.Control.ToArgb() == Color.Black.ToArgb();
		}
 
		protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e) {
	        Image image = e.Image;
			if (image != null) {
                if (Image.GetPixelFormatSize(image.PixelFormat) > 16) {
                    // for 24, 32 bit images, just paint normally - mapping the color table is not
                    // going to work when you can have full color.
                    base.OnRenderItemImage(e);
                    return;
                }
				Graphics g = e.Graphics;
			
				ToolStripItem item = e.Item;
				Rectangle imageRect = e.ImageRectangle;
				using (ImageAttributes attrs = new ImageAttributes()) {
					if (IsHighContrastWhiteOnBlack() && !(FillWhenSelected && (e.Item.Pressed || e.Item.Selected))) {
						// translate white, black and blue to colors visible in high contrast mode.
						ColorMap cm1 = new ColorMap();
						ColorMap cm2 = new ColorMap();
						ColorMap cm3 = new ColorMap();
 
						cm1.OldColor = Color.Black;
						cm1.NewColor = Color.White;
						cm2.OldColor = Color.White;
						cm2.NewColor = Color.Black;
						cm3.OldColor = Color.FromArgb(0, 0, 128);
						cm3.NewColor = Color.White;
 
 
						attrs.SetRemapTable(new ColorMap[] { cm1, cm2, cm3 }, ColorAdjustType.Bitmap);
					}
					if (item.ImageScaling == ToolStripItemImageScaling.None) {
						g.DrawImage(image, imageRect, 0, 0, imageRect.Width, imageRect.Height, GraphicsUnit.Pixel, attrs);
					}
					else {
						g.DrawImage(image, imageRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attrs);
					}
				}
			}
		}
 
		protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) {
			if (FillWhenSelected) {
                ToolStripButton button = e.Item as ToolStripButton;
                if (button != null && button.Checked) {
                    Graphics g = e.Graphics;
                    Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
 
                    if (button.CheckState == CheckState.Checked) {
                        g.FillRectangle(SystemBrushes.Highlight, bounds);
                    }
                    if (button.Selected && AccessibilityImprovements.Level1) {
                        g.DrawRectangle(SystemPens.Highlight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
                    }
                    else {
                        g.DrawRectangle(SystemPens.ControlLight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
                    }
                }
                else {
    				RenderItemInternalFilled(e);
                }
			}
			else {
				base.OnRenderButtonBackground(e);
			}
		}
 
		private void RenderItemInternalFilled(ToolStripItemRenderEventArgs e) {
			RenderItemInternalFilled(e, /*pressFill=*/true);
		}
 
		private void RenderItemInternalFilled(ToolStripItemRenderEventArgs e, bool pressFill) {
			Graphics g = e.Graphics;
			Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
            
			if (e.Item.Pressed) {
				if (pressFill) {
					g.FillRectangle(SystemBrushes.Highlight, bounds);
				}
				else {
					g.DrawRectangle(SystemPens.ControlLight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
				}
			}
			else if (e.Item.Selected) {
				g.FillRectangle(SystemBrushes.Highlight, bounds);
				g.DrawRectangle(SystemPens.ControlLight, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
			}
         
                   
		}
 
	}
}