更改MenuStrip的外观 让它不再是系统默认的外观 美观的界面总是让人赏心悦目的 文章都比较简单 但是效果很好 很适合像我这样的初学者
我在程序员之窗看到过这样的文章 但自己水平有限 没能实现像他所说的那样的美化 不能完全实现.NET类库提供的渲染菜单外观的抽象类,所以集成了一个专用类 并重写其中一些方法,实现的外观的更改,看看效果:
这里 我们自定义一个控件 继承自系统的MenuStrip MenuStrip具有一个Renderer属性 此属性接受一个 System.Windows.Forms.ToolStripRenderer类的对象 这个类定义了菜单 工具栏的外观 此类是一个抽象类 系统菜单外观是由ToolStripProfessionalRenderer类定义的 ToolStripProfessionalRenderer类就继承自System.Windows.Forms.ToolStripRenderer
我们为了减少工作量不用去继承ToolStripRenderer这个抽象类 ToolStripProfessionalRenderer定义了菜单栏 工具栏的外观 我们继承这个专业类 重写它一些方法来自定义外观。所以主要就是实现定义外观的类
先建立一个类CustomProfessionalRenderer继承自System.Windows.Forms.ToolStripProfessionalRenderer
给这个类添加主题颜色的字段 重载其构造函数给字段赋值 以便创建不同色调的渲染对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 public CustomProfessionalRenderer():base()
3 {
4 }
5 public CustomProfessionalRenderer(Color color):base()
6 {
7 _color = color;
8 }
添加一个辅助函数 用来获取圆角矩形区域
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 public static GraphicsPath GetRoundedRectPath(Rectangle rect, int radius)
3 {
4 int diameter = radius;
5 Rectangle arcRect = new Rectangle(rect.Location, new Size(diameter, diameter));
6 GraphicsPath path = new GraphicsPath();
7
8 // 左上角
9 path.AddArc(arcRect, 180, 90);
10
11 // 右上角
12 arcRect.X = rect.Right - diameter;
13 path.AddArc(arcRect, 270, 90);
14
15 // 右下角
16 arcRect.Y = rect.Bottom - diameter;
17 path.AddArc(arcRect, 0, 90);
18
19 // 左下角
20 arcRect.X = rect.Left;
21 path.AddArc(arcRect, 90, 90);
22 path.CloseFigure();
23 return path;
24 }
然后重写基类的一些方法 更改外观
渲染背景
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
3 {
4 ToolStrip toolStrip = e.ToolStrip;
5 Graphics g = e.Graphics;
6 g.SmoothingMode = SmoothingMode.HighQuality;//抗锯齿
7 Rectangle bounds = e.AffectedBounds;
8 LinearGradientBrush lgbrush = new LinearGradientBrush(new Point(0, 0), new Point(0, toolStrip.Height), Color.FromArgb(255,Color.White), Color.FromArgb(150,_color));
9 if (toolStrip is MenuStrip)
10 {
11 //由menuStrip的Paint方法定义 这里不做操作
12 }
13 else if (toolStrip is ToolStripDropDown)
14 {
15 int diameter = 10;//直径
16 GraphicsPath path = new GraphicsPath();
17 Rectangle rect = new Rectangle(Point.Empty, toolStrip.Size);
18 Rectangle arcRect = new Rectangle(rect.Location, new Size(diameter, diameter));
19
20 path.AddLine(0, 0, 10, 0);
21 // 右上角
22 arcRect.X = rect.Right - diameter;
23 path.AddArc(arcRect, 270, 90);
24
25 // 右下角
26 arcRect.Y = rect.Bottom - diameter;
27 path.AddArc(arcRect, 0, 90);
28
29 // 左下角
30 arcRect.X = rect.Left;
31 path.AddArc(arcRect, 90, 90);
32 path.CloseFigure();
33 toolStrip.Region = new Region(path);
34 g.FillPath(lgbrush, path);
35 }
36 else
37 {
38 base.OnRenderToolStripBackground(e);
39 }
40 }
渲染边框
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
//不调用基类的方法 屏蔽掉该方法 去掉边框
}
渲染箭头颜色
2 protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
3 {
4 e.ArrowColor = _color;
5 base.OnRenderArrow(e);
6 }
渲染菜单项
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
3 {
4 Graphics g = e.Graphics;
5 ToolStripItem item = e.Item;
6 ToolStrip toolstrip = e.ToolStrip;
7
8
9 //渲染顶级项
10 if (toolstrip is MenuStrip)
11 {
12 LinearGradientBrush lgbrush = new LinearGradientBrush(new Point(0, 0), new Point(0, item.Height), Color.FromArgb(100, Color.White), Color.FromArgb(0, Color.White));
13 SolidBrush brush=new SolidBrush(Color.FromArgb(255,Color.White));
14 if (e.Item.Selected)
15 {
16 GraphicsPath gp = GetRoundedRectPath(new Rectangle(new Point(0, 0), item.Size), 5);
17 g.FillPath(lgbrush, gp);
18 }
19 if (item.Pressed)
20 {
21 ////创建上面左右2圆角的矩形路径
22 //GraphicsPath path = new GraphicsPath();
23 //int diameter = 8;
24 //Rectangle rect = new Rectangle(Point.Empty, item.Size);
25 //Rectangle arcRect = new Rectangle(rect.Location, new Size(diameter, diameter));
26 //// 左上角
27 //path.AddArc(arcRect, 180, 90);
28 //// 右上角
29 //arcRect.X = rect.Right - diameter;
30 //path.AddArc(arcRect, 270, 90);
31 //path.AddLine(new Point(rect.Width, rect.Height), new Point(0, rect.Height));
32 //path.CloseFigure();
33 ////填充路径
34 //g.FillPath(brush, path);
35 g.FillRectangle(Brushes.White,new Rectangle(Point.Empty,item.Size));
36 }
37 }
38 //渲染下拉项
39 else if (toolstrip is ToolStripDropDown)
40 {
41 g.SmoothingMode = SmoothingMode.HighQuality;
42 LinearGradientBrush lgbrush = new LinearGradientBrush(new Point(0, 0), new Point(item.Width, 0), Color.FromArgb(200, _color), Color.FromArgb(0, Color.White));
43 if (item.Selected)
44 {
45 GraphicsPath gp = GetRoundedRectPath(new Rectangle(0, 0, item.Width, item.Height), 10);
46 g.FillPath(lgbrush, gp);
47 }
48 }
49 else
50 {
51 base.OnRenderMenuItemBackground(e);
52 }
53 }
渲染分界线
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 {
3 Graphics g = e.Graphics;
4
5 LinearGradientBrush lgbrush = new LinearGradientBrush(new Point(0, 0), new Point(e.Item.Width, 0), _color, Color.FromArgb(0, _color));
6 g.FillRectangle(lgbrush, new Rectangle(3,e.Item.Height/2,e.Item.Width,1));
7 //base.OnRenderSeparator(e);
8 }
渲染下拉菜单的左边图片区域
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
3 {
4 //base.OnRenderImageMargin(e);
5 //屏蔽掉左边图片竖条
6 }
到此 主要方法重写得差不多了 重写其它的方法 还可以控制其它的外观 比如选中状态下的项左边的小钩等等
接下来创建控件 继承自MenuStrip 并设计一个themeColor属性 对外提高更改主题颜色的API
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 {
3 private Color _themeColor = Color.Gray;
4 public CustomContrls_MenuStrip()
5 {
6 InitializeComponent();
7 this.Renderer = new CustomProfessionalRenderer(_themeColor);
8 }
9 public Color ThemeColor
10 {
11 get { return _themeColor; }
12 set
13 {
14 _themeColor = value;
15 this.Renderer = new CustomProfessionalRenderer(_themeColor);
16 }
17 }
18 }
这样就制作好了我们自定义的MenuStrip控件,该控件保留了系统菜单控件的所有功能并增加了一个属性 用于更换菜单风格 把CustomContrls_MenuStrip拖到IDE中的窗体上开始使用了
通过少量的修改 实现比较美观的外观 是最明智的选择 不必把过多的精力放到界面上