更改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 else37 {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 else50 {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 ThemeColor10 {11 get { return _themeColor; }12 set13 {14 _themeColor = value;15 this.Renderer = new CustomProfessionalRenderer(_themeColor);16 }17 }18 }
這樣就製作好了我們自訂的MenuStrip控制項,該控制項保留了系統功能表控制項的所有功能並增加了一個屬性 用於更換菜單風格 把CustomContrls_MenuStrip拖到IDE中的表單上開始使用了
通過少量的修改 實現比較美觀的外觀 是最明智的選擇 不必把過多的精力放到介面上