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