更改MenuStrip的外观 让它不再是系统默认的外观 美观的界面总是让人赏心悦目的 文章都比较简单 但是效果很好 很适合像我这样的初学者
我在程序员之窗看到过这样的文章 但自己水平有限 没能实现像他所说的那样的美化 不能完全实现.NET类库提供的渲染菜单外观的抽象类,所以集成了一个专用类 并重写其中一些方法,实现的外观的更改,看看效果:
这里 我们自定义一个控件 继承自系统的MenuStrip MenuStrip具有一个Renderer属性 此属性接受一个 System.Windows.Forms.ToolStripRenderer类的对象 这个类定义了菜单 工具栏的外观 此类是一个抽象类 系统菜单外观是由ToolStripProfessionalRenderer类定义的 ToolStripProfessionalRenderer类就继承自System.Windows.Forms.ToolStripRenderer
我们为了减少工作量不用去继承ToolStripRenderer这个抽象类 ToolStripProfessionalRenderer定义了菜单栏 工具栏的外观 我们继承这个专业类 重写它一些方法来自定义外观。所以主要就是实现定义外观的类
先建立一个类CustomProfessionalRenderer继承自System.Windows.Forms.ToolStripProfessionalRenderer
给这个类添加主题颜色的字段 重载其构造函数给字段赋值 以便创建不同色调的渲染对象
1 private Color _color = Color.Red;
2 public CustomProfessionalRenderer():base()
3 {
4 }
5 public CustomProfessionalRenderer(Color color):base()
6 {
7 _color = color;
8 }
添加一个辅助函数 用来获取圆角矩形区域
1 //获取圆角矩形区域 radius=直径
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 }
然后重写基类的一些方法 更改外观
渲染背景
1 //渲染背景 包括menustrip背景 toolstripDropDown背景
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) { //不调用基类的方法 屏蔽掉该方法 去掉边框 }
渲染箭头颜色
1 //渲染箭头 更改箭头颜色 2 protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) 3 { 4 e.ArrowColor = _color; 5 base.OnRenderArrow(e); 6 }
渲染菜单项
1 //渲染项 不调用基类同名方法 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 }
渲染分界线
1 protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) 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 }
渲染下拉菜单的左边图片区域
1 //渲染图片区域 下拉菜单左边的图片区域 2 protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) 3 { 4 //base.OnRenderImageMargin(e); 5 //屏蔽掉左边图片竖条 6 }
到此 主要方法重写得差不多了 重写其它的方法 还可以控制其它的外观 比如选中状态下的项左边的小钩等等
接下来创建控件 继承自MenuStrip 并设计一个themeColor属性 对外提高更改主题颜色的API
1 public partial class CustomContrls_MenuStrip : MenuStrip 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中的窗体上开始使用了
通过少量的修改 实现比较美观的外观 是最明智的选择 不必把过多的精力放到界面上