• 用c#绘制Office2003样式的菜单


    我的方法是重写MenuItem类,在写的过程中发现用GDI+实际测量出来的文本的大小不是很准确,还有文本也不能很好对齐,固在代码里可以时常看到很多多加上去的数字.我想原理就不用我讲了吧,下面的代码注释的很
    清楚了:
    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    namespace OfficeMenu
    {
     /// <summary>
     /// Class1 的摘要说明。
     /// </summary>
     public class OfficeMenuItem:MenuItem
     {
      public OfficeMenuItem(bool IsApplyOfficeMenu,string ItemText)
      {
       if(IsApplyOfficeMenu)
       {
        this.Text=ItemText;
        this.OwnerDraw=true;
        font=new Font("宋体",9f,GraphicsUnit.Point);
       }
       else
       {
        this.Text=ItemText;
        this.OwnerDraw=false;
       }
      }

      private Font font;
      private StringFormat strFormat=new StringFormat();
      private string ItemText="";
      private string iconPath="";

      //定义绘制的时候的各种笔刷
      private LinearGradientBrush TopMenuHostLightBrush;
      private SolidBrush TopMenuDefaultBrush;
      private SolidBrush FontDefaultBrush;
      private LinearGradientBrush TopMenuSelectedBrush;
      private SolidBrush MenuDefaultBrush;
      private SolidBrush MenuDefaultSelectedBrush;
      private SolidBrush MenuCheckBrush;
      private LinearGradientBrush MenuSideBarBrush;
      private SolidBrush MenuDefaultGrayedBrush;
      //定义绘制的时候所需的各种线条
      private Pen TopMenuPen;
      private Pen MenuDefaultPen;
      //定义需要的矩形结构
      private Rectangle SideBarRect;
      private Rectangle CheckedRect;
      private Rectangle TopMenuRect;
      private Rectangle ShortcutRect;

      //定义图标
      public string IconPath
      {
       get
       {
        return iconPath;
       }
       set
       {
        iconPath=value;
       }
      }

      //判断菜单是否是顶级菜单
      private bool CheckIsTop()
      {
       if(typeof(MainMenu)==this.Parent.GetType())
       {
        return true;
       }
       else
       {
        return false;
       }
      }
      //获取菜单的快捷键
      private string GetShortCut()
      {
       string shortcut="";
       try
       {
        if(this.ShowShortcut==true && (!this.IsParent) && (!(this.Shortcut==Shortcut.None)))
        {
         shortcut=this.Shortcut.ToString();
         shortcut=shortcut.Replace("Ctrl","Ctrl+");
         shortcut=shortcut.Replace("Alt","Alt+");
         shortcut=shortcut.Replace("Shift","Shift+");
        }
       }
       catch
       {
        return "";
       }
       return shortcut;
      }
      //重写测量函数
      protected override void OnMeasureItem(MeasureItemEventArgs e)
      {
       base.OnMeasureItem (e);

       try
       {
        ItemText=this.Text;
        SizeF SizeMenuText;
        if(this.ItemText=="-") //设置分割线的高度
        {
         e.ItemHeight=5;
         return;
        }

        string getedShortcut=this.GetShortCut();
        if(!this.CheckIsTop()) //如果不是顶级菜单
        {
         SizeMenuText=e.Graphics.MeasureString(ItemText+"".PadRight(4,' ')+getedShortcut,this.font);
         e.ItemWidth=Convert.ToInt32(SizeMenuText.Width)+26;
        }
        else
        {
         SizeMenuText=e.Graphics.MeasureString(ItemText,this.font);
         e.ItemWidth=Convert.ToInt32(SizeMenuText.Width)-4;
        }
        if(this.Visible)
        {
         e.ItemHeight=Convert.ToInt32(SizeMenuText.Height)+6;
        }
        else
        {
         e.ItemHeight=0;
        }
        
       }
       catch
       {
        e.ItemHeight=20;
        e.ItemWidth=80;
       }
      }
      //重写绘图函数
      protected override void OnDrawItem(DrawItemEventArgs e)
      {
       if(this.Visible)
       {
        base.OnDrawItem (e);
        Rectangle MenuRect=e.Bounds;
        ItemText=this.Text;
        Graphics g=e.Graphics;

        //绘制边框时需要的特殊矩形
        SideBarRect=new Rectangle(MenuRect.X,MenuRect.Y,25,MenuRect.Height);
        //绘制选择框时需要的矩形
        CheckedRect=new Rectangle(MenuRect.X+1,MenuRect.Y+1,24,MenuRect.Height-2);
        //绘制顶菜单时需要的矩形
        TopMenuRect=new Rectangle(MenuRect.X+1,MenuRect.Y+3,MenuRect.Width,MenuRect.Height);
        //绘制shortcut用到的矩形
        ShortcutRect=new Rectangle(MenuRect.X,MenuRect.Y+4,MenuRect.Width-10,MenuRect.Height);

        //定义绘制的时候的各种笔刷
        TopMenuHostLightBrush=new LinearGradientBrush(MenuRect,Color.White,Color.FromArgb(220,134,56),90f); //顶级菜单发生HOTLIGHT 时显示的颜色
        TopMenuDefaultBrush=new SolidBrush(SystemColors.Control); //顶级菜单默认的颜色
        FontDefaultBrush=new SolidBrush(Color.Black); //字体默认的颜色
        TopMenuSelectedBrush=new LinearGradientBrush(MenuRect,Color.White,Color.FromArgb(95,109,126),90f); //顶级菜单选中时的颜色
        MenuDefaultBrush=new SolidBrush(Color.White); //默认菜单的颜色
        MenuDefaultSelectedBrush=new SolidBrush(Color.FromArgb(247,218,157)); //菜单选中时的颜色
        MenuCheckBrush=new SolidBrush(Color.FromArgb(225,143,70)); //当菜单CHECKED属性为真的时显示的颜色
        MenuSideBarBrush=new LinearGradientBrush(SideBarRect,Color.White,Color.FromArgb(149,160,174),0f);//绘制侧栏
        MenuDefaultGrayedBrush=new SolidBrush(Color.FromArgb(105,105,105));//菜单不可用时
        //定义绘制的时候所需的各种线条
        TopMenuPen=new Pen(Brushes.Black,1f);  //顶级菜单的边框
        MenuDefaultPen=new Pen(new SolidBrush(Color.FromArgb(60,60,115)),1f); //正常选择时的边框

        //开始绘制****************************************************
        if(this.CheckIsTop() && this.ItemText!="-") //如果是顶级菜单
        {
         bool IsDraw=false;//定义一个变量保证正常显示的只绘制一次 避免浪费资源
         strFormat.Alignment=StringAlignment.Center;
         if(IsDraw==false) //绘制正常显示时的图像
         {
          g.FillRectangle(TopMenuDefaultBrush,MenuRect);
          g.DrawString(ItemText,this.font,FontDefaultBrush,TopMenuRect,strFormat);
         }

         //绘制HOTLIGHT时的图像
         if((e.State & DrawItemState.HotLight)==DrawItemState.HotLight)  //突出显示时
         {
          g.FillRectangle(TopMenuHostLightBrush,MenuRect);
          g.DrawRectangle(TopMenuPen,MenuRect.X,MenuRect.Y,MenuRect.Width-1,MenuRect.Height-1);
          g.DrawString(ItemText,this.font,FontDefaultBrush,TopMenuRect,strFormat);
          IsDraw=true;
         }
         //绘制菜单选中时的图像
         if((e.State & DrawItemState.Selected)==DrawItemState.Selected)
         {
          g.FillRectangle(TopMenuSelectedBrush,MenuRect);
          g.DrawRectangle(TopMenuPen,MenuRect.X,MenuRect.Y,MenuRect.Width-1,MenuRect.Height-1);
          g.DrawString(ItemText,this.font,FontDefaultBrush,TopMenuRect,strFormat);
          IsDraw=true;
         }
        }
        else  //非顶级菜单时
        {
         if(this.ItemText!="-")
         {
          bool IsDraw=false;
          if(IsDraw==false) //正常显示时
          {
           g.FillRectangle(MenuDefaultBrush,MenuRect);
           g.FillRectangle(MenuSideBarBrush,MenuRect.X,MenuRect.Y,25,MenuRect.Height);
           g.DrawString(ItemText,this.font,FontDefaultBrush,MenuRect.X+26,MenuRect.Y+4);
           //绘制shortcut
           string shortcut=this.GetShortCut();
           strFormat.Alignment=StringAlignment.Far;
           g.DrawString(shortcut,this.font,FontDefaultBrush,ShortcutRect,strFormat);
           //绘制图标
           this.DrawIcon(g);
          }

          if((e.State & DrawItemState.Selected)==DrawItemState.Selected) //选中时
          {
           this.DrawItem_Selected(g,MenuRect,ItemText);
           IsDraw=true;
          }

          if((e.State & DrawItemState.Grayed)==DrawItemState.Grayed) //不可用时
          {
           g.DrawString(ItemText,this.font,MenuDefaultGrayedBrush,MenuRect.X+26,MenuRect.Y+4);
           IsDraw=true;
          }

          if(!this.IsParent)
          {
           if((e.State & DrawItemState.Checked)==DrawItemState.Checked) //选择时
           {
            g.FillRectangle(MenuCheckBrush,CheckedRect);
            g.DrawRectangle(new Pen(Brushes.Black,1f),MenuRect.X+1,MenuRect.Y+1,23,MenuRect.Height-3);
            g.DrawString("√",this.font,FontDefaultBrush,MenuRect.X+3,MenuRect.Y+4);
            IsDraw=true;
           }

           if(this.Checked==true && ((e.State & DrawItemState.Selected)==DrawItemState.Selected)) //选中且Checked属性为真时
           {
            g.FillRectangle(new SolidBrush(Color.FromArgb(255,91,91)),CheckedRect);
            g.DrawRectangle(new Pen(Brushes.Black,1f),MenuRect.X+1,MenuRect.Y+1,23,MenuRect.Height-3);
            g.DrawString("√",this.font,FontDefaultBrush,MenuRect.X+3,MenuRect.Y+4);
            IsDraw=true;
           }
          }
         }
         else //画分割线
         {
          SolidBrush PartitionLineBrush=new SolidBrush(Color.FromArgb(128,128,128));
          Pen PartitionPen=new Pen(PartitionLineBrush,1f);
          g.FillRectangle(MenuDefaultBrush,MenuRect);
          g.FillRectangle(MenuSideBarBrush,MenuRect.X,MenuRect.Y,25,MenuRect.Height);
          g.DrawLine(PartitionPen,new Point(MenuRect.X+27,MenuRect.Y+2),new Point(MenuRect.X+27+(MenuRect.Width-26),MenuRect.Y+2));
         }


        }
       }
      }

      //画图标
      private void DrawIcon(Graphics g)
      {
       if(this.CheckIsTop()==false && this.IconPath!="" && this.IsParent==false && this.Checked==false)
       {
        try
        {
         Bitmap iconImage=new Bitmap(this.IconPath);
         int imageWidth=iconImage.Width;
         int imageHeight=iconImage.Height;
         if(imageWidth<=CheckedRect.Width && imageHeight<=CheckedRect.Height)
         {
          int ImageRecWidthMistake=CheckedRect.Width-imageWidth;
          float Mistake_2=(float)ImageRecWidthMistake/2f;
          g.DrawImage(iconImage,CheckedRect.X+(int)Mistake_2,CheckedRect.Y,imageWidth,imageHeight);
         }
         else
         {
          g.DrawImage(iconImage,CheckedRect);
         }
        }
        catch
        {
         throw new IconNotFindException("不能创建图标,可能是路径不能也可能是不支持此格式");
        }
       }
      }
      //由于再绘制的过程中选中的动作时需要执行两次一样的代码 固在这里用了一个函数
      private void DrawItem_Selected(Graphics g,Rectangle rec,string itemtext)
      {
       SolidBrush tmpBrush;
       if(this.Enabled)
       {
        tmpBrush=FontDefaultBrush;
       }
       else
       {
        tmpBrush=MenuDefaultGrayedBrush;
       }

       //正常显示
       g.FillRectangle(MenuDefaultSelectedBrush,rec);
       g.DrawRectangle(MenuDefaultPen,rec.X,rec.Y,rec.Width-1,rec.Height-1);
       g.DrawString(itemtext,this.font,tmpBrush,rec.X+26,rec.Y+4);

       //显示shortcut
       string shortcut=this.GetShortCut();
       strFormat.Alignment=StringAlignment.Far;
       g.DrawString(shortcut,this.font,tmpBrush,ShortcutRect,strFormat);
       //画图标
       this.DrawIcon(g);
      }
     }


     //自定义异常
     public class IconNotFindException:ApplicationException
     {
      public IconNotFindException(string message)
       :base(message)
      {
      }
     }
    }

  • 相关阅读:
    【马克-to-win】学习笔记—— 第五章 异常Exception
    【马克-to-win】—— 学习笔记
    Eclipse 日文乱码怎么解决Shift_JIS
    DB2设置code page(日文943)
    如何得到一个接口所有的实现类(及子接口)?例如:Eclipse IDE
    【VBA】随机数
    【VBA】利用Range声明Array(一维/二维)
    【VBA】Do While……Loop循环,遍历某列
    【58沈剑架构系列】DB主从一致性架构优化4种方法
    【58沈剑架构系列】主从DB与cache一致性
  • 原文地址:https://www.cnblogs.com/bluewelkin/p/1272066.html
Copyright © 2020-2023  润新知