|
#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);
}
}
}
}
|