zoukankan      html  css  js  c++  java
  • 用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)
      {
      }
     }
    }

  • 相关阅读:
    LeetCode120 Triangle
    LeetCode119 Pascal's Triangle II
    LeetCode118 Pascal's Triangle
    LeetCode115 Distinct Subsequences
    LeetCode114 Flatten Binary Tree to Linked List
    LeetCode113 Path Sum II
    LeetCode112 Path Sum
    LeetCode111 Minimum Depth of Binary Tree
    Windows下搭建PHP开发环境-WEB服务器
    如何发布可用于azure的镜像文件
  • 原文地址:https://www.cnblogs.com/bluewelkin/p/1272066.html
Copyright © 2011-2022 走看看