C# 中的可自定义主菜单






3.08/5 (9投票s)
2004年12月24日
3分钟阅读

130796

848
一篇关于自定义主菜单和所有者绘制的文章。
引言
本文介绍了一种在 C# 中自定义应用程序主菜单的方法。它可以完全且轻松地更改。这是我的第一篇文章,我希望它能有所帮助。
背景
我从这个页面找到的代码编写了这篇文章,我强烈建议阅读它。实际上,代码非常相似,主要区别在于我解决了原始代码中的一些限制。第一个限制是原始文章中提供的代码设置了菜单项的大小,这意味着它们不是动态的。第二个限制在于,当你绘制自己的菜单时,所有特殊字符(如分隔符“-”字符(创建一条分隔两个项目的线))都无法识别。还有另一个限制。你不能更改菜单的颜色,只能更改项目的颜色!菜单的其余部分(你没有创建项目的地方)不会更改其颜色。尝试按照原始文章创建菜单,但将菜单设置为蓝色,你就会明白我的意思。
使用代码
我们的想法是创建一个常规的主菜单,然后定义OwnerDraw
变量,以便我们必须进行绘制,然后定义DrawItem()
和MeasureItem()
函数来绘制我们的菜单。我们将必须对菜单中的每个项目都这样做。幸运的是,我们只需要创建两个DrawItem()
和MeasureItem()
函数即可完成这项工作。一个负责主菜单项,另一个负责当我们点击主菜单项时弹出的下拉菜单。
为了解决颜色问题,我们必须创建一个额外的主菜单项,该项将被禁用,然后为了绘制它,我们将使用一个特殊的函数。
- 像往常一样创建你的菜单(使用工具箱中的
MainMenu
或其他),并创建一个额外的主菜单项。 - 在Items属性中,将
OwnerDraw
参数定义为True,并在“extra”项中,将Enable
参数设置为False。 - 将此代码添加到你的应用程序
//Some colors I'll use. private Color grad1=Color.FromArgb(165,194,245); private Color grad2=Color.FromArgb(209,232,255); private Color grad3=Color.FromArgb(255,210,151); private Color grad4=Color.FromArgb(241,241,231); private Color linhalight=Color.FromArgb(169,184,215); private Color linha=Color.FromArgb(10,47,115); // //This is where we draw the main menu items. // private void OnDrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e) { //rectangle that contains the dimentions of the item. Rectangle rc = new Rectangle(e.Bounds.X , e.Bounds.Y, e.Bounds.Width, e.Bounds.Height); //draws the button. e.Graphics.FillRectangle(new SolidBrush(grad1),rc); // Cast the sender to MenuItem so you can access text property. MenuItem customItem = (MenuItem) sender; // Create a Brush and a Font to draw the item's text. System.Drawing.Brush aBrush = System.Drawing.Brushes.Black; Font aFont = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular, GraphicsUnit.Point); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; rc.Y+=3; e.Graphics.DrawString(customItem.Text, aFont, aBrush, rc , sf ); rc.Y-=3; //if the mouse is hover the item it changes the looks. if (e.State==(DrawItemState.NoAccelerator | DrawItemState.HotLight)) { e.Graphics.FillRectangle(new LinearGradientBrush(rc,grad4, grad3,LinearGradientMode.Vertical) , rc); rc.Y+=3; e.Graphics.DrawString( customItem.Text , aFont , new SolidBrush(Color.Black), rc ,sf); rc.Y-=3; rc.Width--; e.Graphics.DrawRectangle(new Pen(Color.Blue,1), rc ); rc.Width++; } else { //if the mouse hits the item it changes the looks. if ( e.State==(DrawItemState.NoAccelerator | DrawItemState.Selected)) { e.Graphics.FillRectangle(new LinearGradientBrush(rc, grad2,grad1,LinearGradientMode.Vertical) , rc); rc.Y+=3; e.Graphics.DrawString( customItem.Text , aFont , new SolidBrush(Color.Black), rc ,sf); rc.Y-=3; rc.Width--; e.Graphics.DrawRectangle(new Pen(new SolidBrush(linha)), rc ); rc.Width++; e.Graphics.DrawLine(new Pen(linhalight,1),rc.X , rc.Bottom, rc.Right, rc.Bottom); } else e.Graphics.DrawLine(new Pen(Color.White,1),rc.X , rc.Bottom, rc.Right, rc.Bottom); } //draws the the focus rectangle. e.DrawFocusRectangle(); } // //This is where we set the main menu items size. // private void OnMeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e) { // Cast the sender to MenuItem so you can access text property. MenuItem customItem = (MenuItem) sender; // Create a Brush and a Font to draw the item's text. Font aFont = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular, GraphicsUnit.Point); //Gets the size of the drawn string. SizeF stringSize = e.Graphics.MeasureString(customItem.Text, aFont); //Sets the size of the menu item. e.ItemWidth=Convert.ToInt32(stringSize.Width); e.ItemHeight=20; } // //This is where we draw the dropdown menu items. // private void OnDrawItemSec(object sender, System.Windows.Forms.DrawItemEventArgs e) { //rectangle that contains the dimentions of the item. Rectangle rc = new Rectangle(e.Bounds.X , e.Bounds.Y, e.Bounds.Width, e.Bounds.Height); //draws the button. e.Graphics.FillRectangle(new SolidBrush(Color.White),rc); // Cast the sender to MenuItem so you can access text property. MenuItem customItem = (MenuItem) sender; // Create a Brush and a Font to draw the item's text. System.Drawing.Brush aBrush = System.Drawing.Brushes.Black; Font aFont = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular, GraphicsUnit.Point); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; //if the text is the separator caracter ('-') draws the separator. if(customItem.Text=="-") e.Graphics.DrawLine(new Pen(Color.DarkGray,1), rc.X,rc.Y+2,rc.X+rc.Right,rc.Y+2); else { rc.Y+=3; e.Graphics.DrawString(customItem.Text, aFont, aBrush, rc , sf ); rc.Y-=3; } //if the mouse is hover the item it changes the looks. if ( e.State==(DrawItemState.NoAccelerator | DrawItemState.Selected)) { e.Graphics.FillRectangle(new SolidBrush(grad1) , rc); rc.Y+=3; e.Graphics.DrawString( customItem.Text , aFont , new SolidBrush(Color.Black), rc ,sf); rc.Y-=3; rc.Height--; rc.Width--; e.Graphics.DrawRectangle(new Pen(new SolidBrush(linha)), rc ); rc.Height++; rc.Width++; } e.DrawFocusRectangle(); } // //This is where we set the dropdown menu items. // private void OnMeasureItemSec(object sender, System.Windows.Forms.MeasureItemEventArgs e) { // Cast the sender to MenuItem so you can access text property. MenuItem customItem = (MenuItem) sender; // Create a Brush and a Font to draw the item's text. Font aFont = new Font("Microsoft Sans Serif", (float)8.25, FontStyle.Regular, GraphicsUnit.Point); //Gets the size of the drawn string. SizeF stringSize = e.Graphics.MeasureString(customItem.Text, aFont); e.ItemWidth=Convert.ToInt32(stringSize.Width); //Sets the size of the menu item.(regards the separator case) if(customItem.Text=="-") e.ItemHeight=5; else e.ItemHeight=20; } // //This is where we draw the extra item to color the remaining menu. // private void OnDrawExtra(object sender, System.Windows.Forms.DrawItemEventArgs e) { Rectangle area = new Rectangle(e.Bounds.X , e.Bounds.Y, this.ClientRectangle.Right- (e.Bounds.X-this.ClientRectangle.X-4), 19); e.Graphics.FillRectangle(new SolidBrush(grad1),area); }
- 现在对于主菜单项,定义它们的事件参数并将
DrawItem
设置为OnDrawItem
(你上面添加的),并将MeasureItem
设置为OnMeasureItem
。对下拉项目执行相同的操作,但这次使用OnDrawItemSec
和OnMeasureItemSec
。对于 extra 项,我们将DrawItem
事件设置为执行OnDrawExtra
。
编译并查看你的菜单的新外观。
限制
此代码是对原始文章中代码的改进,但仍远非完美。例如,“&”特殊字符问题。与“-”问题一样,“&”不是下划线菜单项的关键字符,而是被绘制出来。
示例
项目 -> &View
显示:&View
而不是:View。
另一个问题是菜单下方的“可怕的”白色线条。
希望你喜欢这个控件。
历史
23-12-2004
- 版本 1。