65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的可自定义主菜单

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.08/5 (9投票s)

2004年12月24日

3分钟阅读

viewsIcon

130796

downloadIcon

848

一篇关于自定义主菜单和所有者绘制的文章。

Sample Image

引言

本文介绍了一种在 C# 中自定义应用程序主菜单的方法。它可以完全且轻松地更改。这是我的第一篇文章,我希望它能有所帮助。

背景

我从这个页面找到的代码编写了这篇文章,我强烈建议阅读它。实际上,代码非常相似,主要区别在于我解决了原始代码中的一些限制。第一个限制是原始文章中提供的代码设置了菜单项的大小,这意味着它们不是动态的。第二个限制在于,当你绘制自己的菜单时,所有特殊字符(如分隔符“-”字符(创建一条分隔两个项目的线))都无法识别。还有另一个限制。你不能更改菜单的颜色,只能更改项目的颜色!菜单的其余部分(你没有创建项目的地方)不会更改其颜色。尝试按照原始文章创建菜单,但将菜单设置为蓝色,你就会明白我的意思。

使用代码

我们的想法是创建一个常规的主菜单,然后定义OwnerDraw变量,以便我们必须进行绘制,然后定义DrawItem()MeasureItem()函数来绘制我们的菜单。我们将必须对菜单中的每个项目都这样做。幸运的是,我们只需要创建两个DrawItem()MeasureItem()函数即可完成这项工作。一个负责主菜单项,另一个负责当我们点击主菜单项时弹出的下拉菜单。

为了解决颜色问题,我们必须创建一个额外的主菜单项,该项将被禁用,然后为了绘制它,我们将使用一个特殊的函数。

  1. 像往常一样创建你的菜单(使用工具箱中的MainMenu或其他),并创建一个额外的主菜单项。

    Creation of the menu

  2. Items属性中,将OwnerDraw参数定义为True,并在“extra”项中,将Enable参数设置为False
  3. 将此代码添加到你的应用程序
    //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);
    }
  4. 现在对于主菜单项,定义它们的事件参数并将DrawItem设置为OnDrawItem(你上面添加的),并将MeasureItem设置为OnMeasureItem。对下拉项目执行相同的操作,但这次使用OnDrawItemSecOnMeasureItemSec。对于 extra 项,我们将DrawItem事件设置为执行OnDrawExtra

编译并查看你的菜单的新外观。

限制

此代码是对原始文章中代码的改进,但仍远非完美。例如,“&”特殊字符问题。与“-”问题一样,“&”不是下划线菜单项的关键字符,而是被绘制出来。

示例

项目 -> &View

显示:&View

而不是:View。

另一个问题是菜单下方的“可怕的”白色线条。

希望你喜欢这个控件。

历史

23-12-2004

  • 版本 1。
© . All rights reserved.