RaUI/Source/ryControls/WeifenLuo.WinFormsUI/Docking/VisualStudioToolStripRenderer.cs
zilinsoft 3262955f2f ### 2023-11-07更新
------
#### RaUIV4    V4.0.2311.0701
- *.[全新]整合了MyDb、ryControls、MyDb_MySQL等dll文件到RaUI一个项目。
- *.[新增]新增ApkOp类,可以轻松获取APK信息。
- *.[新增]新增JsonExt扩展类,让Json操作更简单。
- *.[新增]新增WebP类,可以支持webp格式的图片。
- *.[改进]ryQuickSQL中的AddField方法改为自动替换已存在的同名值。
- *.[修复]ryQuickSQL中的AddFieldCalc方法无法正常计算的BUG。
2023-11-07 16:37:53 +08:00

652 lines
24 KiB
C#

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WeifenLuo.WinFormsUI.Docking
{
/// <summary>
///
/// </summary>
public class VisualStudioToolStripRenderer : ToolStripProfessionalRenderer
{
private static Rectangle[] baseSizeGripRectangles =
{
new Rectangle(6,0,1,1),
new Rectangle(6,2,1,1),
new Rectangle(6,4,1,1),
new Rectangle(6,6,1,1),
new Rectangle(4,2,1,1),
new Rectangle(4,4,1,1),
new Rectangle(4,6,1,1),
new Rectangle(2,4,1,1),
new Rectangle(2,6,1,1),
new Rectangle(0,6,1,1)
};
private const int GRIP_PADDING = 4;
private SolidBrush _statusBarBrush;
private SolidBrush _statusGripBrush;
private SolidBrush _statusGripAccentBrush;
private SolidBrush _toolBarBrush;
private SolidBrush _gripBrush;
private Pen _toolBarBorderPen;
private VisualStudioColorTable _table;
private DockPanelColorPalette _palette;
/// <summary>
///
/// </summary>
public bool UseGlassOnMenuStrip { get; set; }
/// <summary>
///
/// </summary>
/// <param name="palette"></param>
public VisualStudioToolStripRenderer(DockPanelColorPalette palette)
: base(new VisualStudioColorTable(palette))
{
_table = (VisualStudioColorTable)ColorTable;
_palette = palette;
RoundedEdges = false;
_statusBarBrush = new SolidBrush(palette.MainWindowStatusBarDefault.Background);
_statusGripBrush = new SolidBrush(palette.MainWindowStatusBarDefault.ResizeGrip);
_statusGripAccentBrush = new SolidBrush(palette.MainWindowStatusBarDefault.ResizeGripAccent);
_toolBarBrush = new SolidBrush(palette.CommandBarToolbarDefault.Background);
_gripBrush = new SolidBrush(palette.CommandBarToolbarDefault.Grip);
_toolBarBorderPen = new Pen(palette.CommandBarToolbarDefault.Border);
UseGlassOnMenuStrip = true;
}
#region Rendering Improvements (includes fixes for bugs occured when Windows Classic theme is on).
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
// Do not draw disabled item background.
if (e.Item.Enabled)
{
bool isMenuDropDown = e.Item.Owner is MenuStrip;
if (isMenuDropDown && e.Item.Pressed)
{
base.OnRenderMenuItemBackground(e);
}
else if (e.Item.Selected)
{
// Rect of item's content area.
Rectangle contentRect = e.Item.ContentRectangle;
// Fix item rect.
Rectangle itemRect = isMenuDropDown
? new Rectangle(
contentRect.X + 2, contentRect.Y - 2,
contentRect.Width - 5, contentRect.Height + 3)
: new Rectangle(
contentRect.X, contentRect.Y - 1,
contentRect.Width, contentRect.Height + 1);
// Border pen and fill brush.
Color pen = ColorTable.MenuItemBorder;
Color brushBegin;
Color brushEnd;
if (isMenuDropDown)
{
brushBegin = ColorTable.MenuItemSelectedGradientBegin;
brushEnd = ColorTable.MenuItemSelectedGradientEnd;
}
else
{
brushBegin = ColorTable.MenuItemSelected;
brushEnd = Color.Empty;
}
DrawRectangle(e.Graphics, itemRect, brushBegin, brushEnd, pen, UseGlassOnMenuStrip);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
var status = e.ToolStrip as StatusStrip;
if (status != null)
{
// IMPORTANT: left empty to remove white border.
return;
}
var context = e.ToolStrip as MenuStrip;
if (context != null)
{
base.OnRenderToolStripBorder(e);
return;
}
var drop = e.ToolStrip as ToolStripDropDown;
if (drop != null)
{
base.OnRenderToolStripBorder(e);
return;
}
var rect = e.ToolStrip.ClientRectangle;
e.Graphics.DrawRectangle(_toolBarBorderPen, new Rectangle(rect.Location, new Size(rect.Width - 1, rect.Height - 1)));
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
var status = e.ToolStrip as StatusStrip;
if (status != null)
{
base.OnRenderToolStripBackground(e);
return;
}
var context = e.ToolStrip as MenuStrip;
if (context != null)
{
base.OnRenderToolStripBackground(e);
return;
}
var drop = e.ToolStrip as ToolStripDropDown;
if (drop != null)
{
base.OnRenderToolStripBackground(e);
return;
}
e.Graphics.FillRectangle(_toolBarBrush, e.ToolStrip.ClientRectangle);
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderStatusStripSizingGrip(ToolStripRenderEventArgs e)
{
// IMPORTANT: below code was taken from Microsoft's reference code (MIT license).
Graphics g = e.Graphics;
StatusStrip statusStrip = e.ToolStrip as StatusStrip;
// we have a set of stock rectangles. Translate them over to where the grip is to be drawn
// for the white set, then translate them up and right one pixel for the grey.
if (statusStrip != null)
{
Rectangle sizeGripBounds = statusStrip.SizeGripBounds;
if (!LayoutUtils.IsZeroWidthOrHeight(sizeGripBounds))
{
Rectangle[] whiteRectangles = new Rectangle[baseSizeGripRectangles.Length];
Rectangle[] greyRectangles = new Rectangle[baseSizeGripRectangles.Length];
for (int i = 0; i < baseSizeGripRectangles.Length; i++)
{
Rectangle baseRect = baseSizeGripRectangles[i];
if (statusStrip.RightToLeft == RightToLeft.Yes)
{
baseRect.X = sizeGripBounds.Width - baseRect.X - baseRect.Width;
}
baseRect.Offset(sizeGripBounds.X, sizeGripBounds.Bottom - 12 /*height of pyramid (10px) + 2px padding from bottom*/);
greyRectangles[i] = baseRect;
if (statusStrip.RightToLeft == RightToLeft.Yes)
{
baseRect.Offset(1, -1);
}
else
{
baseRect.Offset(-1, -1);
}
whiteRectangles[i] = baseRect;
}
g.FillRectangles(_statusGripAccentBrush, whiteRectangles);
g.FillRectangles(_statusGripBrush, greyRectangles);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderGrip(ToolStripGripRenderEventArgs e)
{
Graphics g = e.Graphics;
Rectangle bounds = e.GripBounds;
ToolStrip toolStrip = e.ToolStrip;
bool rightToLeft = (e.ToolStrip.RightToLeft == RightToLeft.Yes);
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)
{
numRectangles++;
// a MenuStrip starts its grip lower and has fewer grip rectangles.
int yOffset = (toolStrip is MenuStrip) ? 2 : 0;
Rectangle[] shadowRects = new Rectangle[numRectangles];
int startY = GRIP_PADDING + 1 + yOffset;
int startX = (width / 2);
for (int i = 0; i < numRectangles; i++)
{
shadowRects[i] = (toolStrip.Orientation == Orientation.Horizontal) ?
new Rectangle(startX, startY, 1, 1) :
new Rectangle(startY, startX, 1, 1);
startY += 4;
}
// in RTL the GripLight rects should paint to the left of the GripDark rects.
int xOffset = (rightToLeft) ? 2 : -2;
if (rightToLeft)
{
// scoot over the rects in RTL so they fit within the bounds.
for (int i = 0; i < numRectangles; i++)
{
shadowRects[i].Offset(-xOffset, 0);
}
}
Brush b = _gripBrush;
for (int i = 0; i < numRectangles - 1; i++)
{
g.FillRectangle(b, shadowRects[i]);
}
for (int i = 0; i < numRectangles; i++)
{
shadowRects[i].Offset(xOffset, -2);
}
g.FillRectangles(b, shadowRects);
for (int i = 0; i < numRectangles; i++)
{
shadowRects[i].Offset(-2 * xOffset, 0);
}
g.FillRectangles(b, shadowRects);
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
{
ToolStripButton button = e.Item as ToolStripButton;
if (button != null && button.Enabled)
{
if (button.Selected || button.Checked)
{
// Rect of item's content area.
Rectangle contentRect = new Rectangle(0, 0, button.Width - 1, button.Height - 1);
Color pen;
Color brushBegin;
Color brushMiddle;
Color brushEnd;
if (button.Checked)
{
if (button.Selected)
{
pen = _table.ButtonCheckedHoveredBorder;
brushBegin = _table.ButtonCheckedHoveredBackground;
brushMiddle = _table.ButtonCheckedHoveredBackground;
brushEnd = _table.ButtonCheckedHoveredBackground;
}
else
{
pen = _table.ButtonCheckedBorder;
brushBegin = ColorTable.ButtonCheckedGradientBegin;
brushMiddle = ColorTable.ButtonCheckedGradientMiddle;
brushEnd = ColorTable.ButtonCheckedGradientEnd;
}
}
else if (button.Pressed)
{
pen = ColorTable.ButtonPressedBorder;
brushBegin = ColorTable.ButtonPressedGradientBegin;
brushMiddle = ColorTable.ButtonPressedGradientMiddle;
brushEnd = ColorTable.ButtonPressedGradientEnd;
}
else
{
pen = ColorTable.ButtonSelectedBorder;
brushBegin = ColorTable.ButtonSelectedGradientBegin;
brushMiddle = ColorTable.ButtonSelectedGradientMiddle;
brushEnd = ColorTable.ButtonSelectedGradientEnd;
}
DrawRectangle(e.Graphics, contentRect,
brushBegin, brushMiddle, brushEnd, pen, false);
}
}
else
{
base.OnRenderButtonBackground(e);
}
}
/// <summary>
///
/// </summary>
/// <param name="toolStrip"></param>
protected override void Initialize(ToolStrip toolStrip)
{
base.Initialize(toolStrip);
// IMPORTANT: enlarge grip area so grip can be rendered fully.
toolStrip.GripMargin = new Padding(toolStrip.GripMargin.All + 1);
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderOverflowButtonBackground(ToolStripItemRenderEventArgs e)
{
var cache = _palette.CommandBarMenuPopupDefault.BackgroundTop;
// IMPORTANT: not 100% accurate as the color change should only happen when the overflow menu is hovered.
// here color change happens when the overflow menu is displayed.
if (e.Item.Pressed)
_palette.CommandBarMenuPopupDefault.BackgroundTop = _palette.CommandBarToolbarOverflowPressed.Background;
base.OnRenderOverflowButtonBackground(e);
if (e.Item.Pressed)
_palette.CommandBarMenuPopupDefault.BackgroundTop = cache;
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
Color color = Color.Black;
var toolStrip = e.ToolStrip;
if (toolStrip is StatusStrip)
{
if (e.Item.Selected)
{
color = _palette.MainWindowStatusBarDefault.HighlightText;
}
else
{
color = _palette.MainWindowStatusBarDefault.Text;
}
}
else if (toolStrip is MenuStrip)
{
var button = e.Item as ToolStripButton;
var checkedButton = button != null && button.Checked;
if (!e.Item.Enabled)
{
color = _palette.CommandBarMenuPopupDisabled.Text;
}
else if (button != null && button.Pressed)
{
color = _palette.CommandBarToolbarButtonPressed.Text;
}
else if (e.Item.Selected && checkedButton)
{
color = _palette.CommandBarToolbarButtonCheckedHovered.Text;
}
else if (e.Item.Selected)
{
color = _palette.CommandBarMenuTopLevelHeaderHovered.Text;
}
else if (checkedButton)
{
color = _palette.CommandBarToolbarButtonChecked.Text;
}
else
{
color = _palette.CommandBarMenuDefault.Text;
}
}
else if (toolStrip is ToolStripDropDown)
{
// This might differ from above branch, but left the same here.
var button = e.Item as ToolStripButton;
var checkedButton = button != null && button.Checked;
if (!e.Item.Enabled)
{
color = _palette.CommandBarMenuPopupDisabled.Text;
}
else if (button != null && button.Pressed)
{
color = _palette.CommandBarToolbarButtonPressed.Text;
}
else if (e.Item.Selected && checkedButton)
{
color = _palette.CommandBarToolbarButtonCheckedHovered.Text;
}
else if (e.Item.Selected)
{
color = _palette.CommandBarMenuTopLevelHeaderHovered.Text;
}
else if (checkedButton)
{
color = _palette.CommandBarToolbarButtonChecked.Text;
}
else
{
color = _palette.CommandBarMenuDefault.Text;
}
}
else
{
// Default color, if not it will be black no matter what
if (!e.Item.Enabled)
{
color = _palette.CommandBarMenuPopupDisabled.Text;
}
else
{
color = _palette.CommandBarMenuDefault.Text;
}
}
TextRenderer.DrawText(e.Graphics, e.Text, e.TextFont, e.TextRectangle, color, e.TextFormat);
}
#region helpers
private static void DrawRectangle(Graphics graphics, Rectangle rect, Color brushBegin,
Color brushMiddle, Color brushEnd, Color penColor, bool glass)
{
RectangleF firstHalf = new RectangleF(
rect.X, rect.Y,
rect.Width, (float)rect.Height / 2);
RectangleF secondHalf = new RectangleF(
rect.X, rect.Y + (float)rect.Height / 2,
rect.Width, (float)rect.Height / 2);
if (brushMiddle.IsEmpty && brushEnd.IsEmpty)
{
graphics.FillRectangle(new SolidBrush(brushBegin), rect);
}
if (brushMiddle.IsEmpty)
{
Brush gradient = new LinearGradientBrush(rect, brushBegin,
brushEnd, LinearGradientMode.Vertical);
graphics.FillRectangle(gradient, rect);
}
else
{
Brush first = new LinearGradientBrush(
firstHalf, brushBegin, brushMiddle, LinearGradientMode.Vertical);
Brush second = new LinearGradientBrush(
secondHalf, brushMiddle, brushEnd, LinearGradientMode.Vertical);
graphics.FillRectangle(first, firstHalf);
graphics.FillRectangle(second, secondHalf);
}
if (glass)
{
Brush glassBrush = new SolidBrush(Color.FromArgb(120, Color.White));
graphics.FillRectangle(glassBrush, firstHalf);
}
if (penColor.A > 0)
{
graphics.DrawRectangle(new Pen(penColor), rect);
}
}
private static void DrawRectangle(Graphics graphics, Rectangle rect, Color brushBegin,
Color brushEnd, Color penColor, bool glass)
{
DrawRectangle(graphics, rect, brushBegin, Color.Empty, brushEnd, penColor, glass);
}
private static void DrawRectangle(Graphics graphics, Rectangle rect, Color brush,
Color penColor, bool glass)
{
DrawRectangle(graphics, rect, brush, Color.Empty, Color.Empty, penColor, glass);
}
private static void FillRoundRectangle(Graphics graphics, Brush brush, Rectangle rect, int radius)
{
float fx = Convert.ToSingle(rect.X);
float fy = Convert.ToSingle(rect.Y);
float fwidth = Convert.ToSingle(rect.Width);
float fheight = Convert.ToSingle(rect.Height);
float fradius = Convert.ToSingle(radius);
FillRoundRectangle(graphics, brush, fx, fy, fwidth, fheight, fradius);
}
private static void FillRoundRectangle(Graphics graphics, Brush brush, float x, float y, float width, float height, float radius)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = GetRoundedRect(rectangle, radius);
graphics.FillPath(brush, path);
}
private static void DrawRoundRectangle(Graphics graphics, Pen pen, Rectangle rect, int radius)
{
float fx = Convert.ToSingle(rect.X);
float fy = Convert.ToSingle(rect.Y);
float fwidth = Convert.ToSingle(rect.Width);
float fheight = Convert.ToSingle(rect.Height);
float fradius = Convert.ToSingle(radius);
DrawRoundRectangle(graphics, pen, fx, fy, fwidth, fheight, fradius);
}
private static void DrawRoundRectangle(Graphics graphics, Pen pen, float x, float y, float width, float height, float radius)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = GetRoundedRect(rectangle, radius);
graphics.DrawPath(pen, path);
}
private static GraphicsPath GetRoundedRect(RectangleF baseRect, float radius)
{
// if corner radius is less than or equal to zero,
// return the original rectangle
if (radius <= 0)
{
GraphicsPath mPath = new GraphicsPath();
mPath.AddRectangle(baseRect);
mPath.CloseFigure();
return mPath;
}
// if the corner radius is greater than or equal to
// half the width, or height (whichever is shorter)
// then return a capsule instead of a lozenge
if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
return GetCapsule(baseRect);
// create the arc for the rectangle sides and declare
// a graphics path object for the drawing
float diameter = radius * 2.0F;
SizeF sizeF = new SizeF(diameter, diameter);
RectangleF arc = new RectangleF(baseRect.Location, sizeF);
GraphicsPath path = new GraphicsPath();
// top left arc
path.AddArc(arc, 180, 90);
// top right arc
arc.X = baseRect.Right - diameter;
path.AddArc(arc, 270, 90);
// bottom right arc
arc.Y = baseRect.Bottom - diameter;
path.AddArc(arc, 0, 90);
// bottom left arc
arc.X = baseRect.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
return path;
}
private static GraphicsPath GetCapsule(RectangleF baseRect)
{
RectangleF arc;
GraphicsPath path = new GraphicsPath();
try
{
float diameter;
if (baseRect.Width > baseRect.Height)
{
// return horizontal capsule
diameter = baseRect.Height;
SizeF sizeF = new SizeF(diameter, diameter);
arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 90, 180);
arc.X = baseRect.Right - diameter;
path.AddArc(arc, 270, 180);
}
else if (baseRect.Width < baseRect.Height)
{
// return vertical capsule
diameter = baseRect.Width;
SizeF sizeF = new SizeF(diameter, diameter);
arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 180, 180);
arc.Y = baseRect.Bottom - diameter;
path.AddArc(arc, 0, 180);
}
else
{
// return circle
path.AddEllipse(baseRect);
}
}
catch
{
path.AddEllipse(baseRect);
}
finally
{
path.CloseFigure();
}
return path;
}
#endregion
// */
#endregion
}
}