在工程化的应用中, 为了取得良好的风格或者具有自身特色的界面,一个重要的方面就是要重绘控件, 菜单作为比较重要的资源,经常在软件中使用,设计漂亮的菜单有助于建立良好的商业化软件。
C#的提供了MenuStrip菜单控件,为了重绘菜单,需要进行建立以MenuStrip为基类的继承类,而C#中,与菜单相关的重写函数均位于ToolStripRenderer,也要重写以ToolStripRenderer作为基类的继承类,在菜单MenuStrip继承类中进行调用。
classCustomMenuStrip : MenuStrip
{
privateColor menu_Color = Color.FromArgb(200, 186, 209, 239);
privateColor selected_Color = Color.FromArgb(200, 175,150,10);
privateColor board_Color = Color.LightGray;
privateColor image_Color = Color.FromArgb(255, 0, 0, 128);
privateColor separator_color = Color.Black;
public CustomMenuStrip()
{
this.Renderer = newCustomProfessionalRenderer(menu_Color, selected_Color, board_Color, image_Color,separator_color);
}
publicvoid SetColor(Color mColor, Color selColor, Color bColor, Color iColor, Color sColor)
{
menu_Color = mColor;
selected_Color = selColor;
board_Color = bColor;
image_Color = iColor;
separator_color = sColor;
this.Renderer = newCustomProfessionalRenderer(menu_Color, selected_Color, board_Color, image_Color,separator_color);
}
}
下来重点在于重写基于ToolStripRenderer的类CustomProfessionalRenderer,在该类中,重载OnRenderToolStripBackground进行菜单背景条和菜单下拉项的重绘
protectedoverridevoid OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
//判断ToolStrip的类型
ToolStrip tsType = e.ToolStrip;
Graphics g = e.Graphics;
//抗锯齿
g.SmoothingMode = SmoothingMode.HighQuality;
if (tsType isMenuStrip ||
tsType isToolStripDropDown)
{
//指定填充Menu栏与ToolBar栏的背景色的画刷,使用线性渐变画刷
Rectangle rect = newRectangle(newPoint(0,0), newSize(tsType.Width-1,tsType.Height-1));
LinearGradientBrush lgBursh = newLinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical);
R0 = menu_color.R;
B0 = menu_color.B;
G0 = menu_color.G;
A0 = menu_color.A;
float[] pos = newfloat[4];
pos[0] = 0.0F;pos[1] = 0.3F; pos[2] = 0.35F; pos[3] = 1.0F;
Color[] colors = newColor[4];
colors[0] =GetColor(0, 35, 24, 9);
colors[1] =GetColor(0, 13, 8, 3);
colors[2] = Color.FromArgb(A0, R0, G0, B0);
colors[3] =GetColor(0, 28, 29, 14);
ColorBlend mix = newColorBlend();
mix.Colors = colors;
mix.Positions = pos;
lgBursh.InterpolationColors = mix;
//填充窗口区域
g.FillRectangle(lgBursh, rect);
if(tsType isMenuStrip)
{
rect = newRectangle(newPoint(1, 1), newSize(tsType.Width - 2, tsType.Height/3 -2));
SolidBrush sBrush = newSolidBrush(Color.FromArgb(100, 255, 255, 255));
g.FillRectangle(sBrush, rect);
sBrush.Dispose();
}
lgBursh.Dispose();
}
elseif (tsType isToolStrip)
{
//指定填充Menu栏与ToolBar栏的背景色的画刷,使用线性渐变画刷
LinearGradientBrush lgBursh = newLinearGradientBrush(newPoint(0, 0),
newPoint(0, tsType.Height),
Color.FromArgb(0, Color.White),
Color.FromArgb(150, Color.LightBlue));
GraphicsPath path = newGraphicsPath(FillMode.Winding);
int diameter = 10;//直径
Rectangle rect = newRectangle(Point.Empty, tsType.Size);
Rectangle arcRect = newRectangle(rect.Location, newSize(diameter, diameter));
path.AddLine(0, 0,10, 0);
// 右上角
arcRect.X =rect.Right - diameter;
path.AddArc(arcRect,270, 90);
// 右下角
arcRect.Y =rect.Bottom - diameter;
path.AddArc(arcRect, 0, 90);
// 左下角
arcRect.X =rect.Left;
path.AddArc(arcRect,90, 90);
path.CloseFigure();
//设置控件的窗口区域
tsType.Region = newRegion(path);
//填充窗口区域
g.FillPath(lgBursh,path);
}
else
{
base.OnRenderToolStripBackground(e);
}
}
protectedoverridevoid OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
//判断ToolStrip的类型
ToolStrip tsType = e.ToolStrip;
Graphics g = e.Graphics;
//抗锯齿
g.SmoothingMode = SmoothingMode.HighQuality;
if (tsType isToolStripDropDown)
{
//设置画笔
Pen LinePen = newPen(board_Color,0.5F);
Rectangle rect = newRectangle(newPoint(1, 1), newSize(tsType.Width - 3, tsType.Height -3));
//画边框
g.DrawRectangle(LinePen, rect);
}
elseif (tsType isToolStrip)
{
//设置画笔
Pen LinePen = newPen(board_Color, 0.5F);
GraphicsPath path = newGraphicsPath();
Rectangle rect = newRectangle(newPoint(-1, -1), newSize(tsType.Width +1, tsType.Height -1));
path.AddRectangle(rect);
//画边框
g.DrawPath(LinePen,path);
}
else
{
base.OnRenderToolStripBorder(e);
}
}
重载OnRenderMenuItemBackground用于绘制菜单某项被鼠标选中时的状态
protectedoverridevoid OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
Graphics g = e.Graphics;
ToolStripItem item = e.Item;
ToolStrip tsType = e.ToolStrip;
g.SmoothingMode = SmoothingMode.HighQuality;
//渲染顶级项
if (tsType isMenuStrip)
{
if (e.Item.Selected)
{
R0 =selected_Color.R;
B0 =selected_Color.B;
G0 =selected_Color.G;
A0 =selected_Color.A;
Rectangle rect = newRectangle(0, 0, item.Size.Width - 1,item.Size.Height - 1);
LinearGradientBrush lgBrush = newLinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical);
float[] pos = newfloat[4];
pos[0] = 0.0F;pos[1] = 0.3F; pos[2] = 0.35F; pos[3] = 1.0F;
Color[] colors = newColor[4];
colors[0] =GetColor(0, 0, 50, 100);
colors[1] =GetColor(0, 0, 0, 30);
colors[2] = Color.FromArgb(A0, R0, G0, B0);
colors[3] =GetColor(0, 0, 50, 100);
ColorBlend mix = newColorBlend();
mix.Colors =colors;
mix.Positions =pos;
lgBrush.InterpolationColors = mix;
g.FillRectangle(lgBrush, rect);
lgBrush.Dispose();
rect = newRectangle(newPoint(1, 1), newSize(tsType.Width - 2, tsType.Height / 3- 2));g.FillRectangle(newSolidBrush(Color.FromArgb(100, 255, 255, 255)),rect);
Pen LinesPen = newPen(board_Color);
Point[] LinePoint = { newPoint(0, 2),
newPoint(item.Size.Width - 1, 2),
newPoint(item.Size.Width - 1,item.Size.Height - 3),
newPoint(0, item.Size.Height - 3),
newPoint(0, 2)};
g.DrawLines(LinesPen, LinePoint);
LinesPen.Dispose();
}if (item.Pressed)
{
Pen LinesPen = newPen(board_Color,0.9F);//FromArgb(197, 228, 253));
Point[] LinePoint = { newPoint(0, 2),
newPoint(item.Size.Width - 1, 2),
newPoint(item.Size.Width - 1,item.Size.Height - 3),
newPoint(0, item.Size.Height - 3),
newPoint(0, 2)};
g.DrawLines(LinesPen, LinePoint);
LinesPen.Dispose();
}
}//渲染下拉项
elseif (tsType isToolStripDropDown)
{
g.SmoothingMode = SmoothingMode.HighQuality;
LinearGradientBrush lgbrush = newLinearGradientBrush(newPoint(0, 0), newPoint(item.Width, item.Height ), Color.FromArgb(250, selected_Color),Color.FromArgb(0, Color.White));
if (item.Selected)
{
GraphicsPath gp = GetRoundedRectPath(newRectangle(0, 0, item.Width, item.Height), 10);
// g.FillPath(lgbrush, gp);
R0 =selected_Color.R;
B0 =selected_Color.B;
G0 = selected_Color.G;
A0 =selected_Color.A;
Rectangle rect = newRectangle(0, 0, item.Size.Width - 1,item.Size.Height - 1);
LinearGradientBrush lgBrush = newLinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical);
float[] pos = newfloat[4];
pos[0] = 0.0F;pos[1] = 0.3F; pos[2] = 0.35F; pos[3] = 1.0F;
Color[] colors = newColor[4];
colors[0] =GetColor(0, 0, 50, 100);
colors[1] =GetColor(0, 0, 0, 30);
colors[2] = Color.FromArgb(A0, R0, G0, B0);
colors[3] =GetColor(0, 0, 50, 100);
ColorBlend mix = newColorBlend();
mix.Colors =colors;
mix.Positions =pos;
lgBrush.InterpolationColors = mix;
g.FillRectangle(lgBrush, rect);
lgBrush.Dispose();
rect = newRectangle(newPoint(1, 1), newSize(item.Size.Width - 2,item.Size.Height / 3 - 2));
g.FillRectangle(newSolidBrush(Color.FromArgb(100, 255, 255, 255)),rect);
Pen LinesPen = newPen(board_Color);
Point[] LinePoint = { newPoint(0, 2),
newPoint(item.Size.Width - 1, 2),
newPoint(item.Size.Width - 1,item.Size.Height - 3),
newPoint(0, item.Size.Height - 3),
newPoint(0, 2)};
g.DrawLines(LinesPen, LinePoint);
LinesPen.Dispose();
}
}
else
{
//base.OnRenderMenuItemBackground(e);
}
}
继承OnRenderSeparator函数以便得到Separator的特定效果
protectedoverridevoid OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
Graphics g = e.Graphics;
ToolStrip tsType = e.ToolStrip;
if (tsType isToolStripDropDown)
{
LinearGradientBrush lgbrush = newLinearGradientBrush(newPoint(0, 0),
newPoint(e.Item.Width, 0),
separator_color,
Color.FromArgb(100,separator_color));
g.FillRectangle(lgbrush, newRectangle(25, e.Item.Height / 2, e.Item.Width / 8 * 7, 1));
}
}
重载OnRenderImageMargin绘制菜单项中右边的显示图标的区域
protectedoverridevoid OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
ToolStripItem item = e.Item;
if (item.Selected)
{
Pen LinesPen = newPen(Color.FromArgb(0, 0, 0));
Point[] LinePoint = { newPoint(0, 2),
newPoint(item.Size.Width - 1, 2),
newPoint(item.Size.Width - 1,item.Size.Height - 3),
newPoint(0, item.Size.Height - 3),
newPoint(0, 2)};
g.DrawLines(LinesPen, LinePoint);
SolidBrush brush = newSolidBrush(Color.FromArgb(197, 228, 253));
Rectangle rect = newRectangle(0, 2, item.Size.Width - 1,item.Size.Height - 5);
g.FillRectangle(brush, rect);
}
else
{
base.OnRenderMenuItemBackground(e);
}
}
至此,就完成了相应的菜单的绘制,得到效果:
具体代码参见: https://download.csdn.net/download/mr_liyonghong/10308638