MAC鱼眼效果菜单控件----------WinForm控件开发系列

  /// <summary>
  /// 鱼眼菜单
  /// </summary>
  [DefaultProperty("Items")]
  [DefaultEvent("FisheyeItemClick")]
  [Description("鱼眼菜单")]
  public partial class FisheyeBarExt : Control
  {
    public delegate void EventHandler(object sender, FisheyeItemEventArgs e);

    private event EventHandler fisheyeItemClick;
    /// <summary>
    /// 鱼眼菜单单击事件
    /// </summary>
    [Description("鱼眼菜单单击事件")]
    public event EventHandler FisheyeItemClick
    {
      add { this.fisheyeItemClick += value; }
      remove { this.fisheyeItemClick -= value; }
    }

    #region

    private bool itemTextShow = false;
    /// <summary>
    /// 是否显示选项文本
    /// </summary>
    [DefaultValue(false)]
    [Description("是否显示选项文本")]
    public bool ItemTextShow
    {
      get { return this.itemTextShow; }
      set
      {
        if (this.itemTextShow == value)
          return;
        this.itemTextShow = value;
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private Font itemTextFont = new Font("宋体", 10);
    /// <summary>
    /// 选项文本字体
    /// </summary>
    [DefaultValue(typeof(Font), "宋体, 10pt")]
    [Description("选项文本字体")]
    public Font ItemTextFont
    {
      get { return this.itemTextFont; }
      set
      {
        if (this.itemTextFont == value)
          return;
        this.itemTextFont = value;
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private Color itemTextColor = Color.White;
    /// <summary>
    /// 选项文本颜色
    /// </summary>
    [DefaultValue(typeof(Color), "White")]
    [Description("选项文本颜色")]
    public Color ItemTextColor
    {
      get { return this.itemTextColor; }
      set
      {
        if (this.itemTextColor == value)
          return;
        this.itemTextColor = value;
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private float proportion = 0.6f;
    /// <summary>
    /// 鱼眼菜单选项默认缩放比例
    /// </summary>
    [DefaultValue(0.6f)]
    [Description("鱼眼菜单选项默认缩放比例")]
    public float Proportion
    {
      get { return this.proportion; }
      set
      {
        if (this.proportion == value)
          return;
        this.proportion = value;
        this.InitializeItems();
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private int itemWidth = 128;
    /// <summary>
    /// 选项宽度
    /// </summary>
    [DefaultValue(128)]
    [Description("选项宽度")]
    public int ItemWidth
    {
      get { return this.itemWidth; }
      set
      {
        if (this.itemWidth == value)
          return;
        this.itemWidth = value;
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private int itemHeight = 128;
    /// <summary>
    /// 选项高度
    /// </summary>
    [DefaultValue(128)]
    [Description("选项高度")]
    public int ItemHeight
    {
      get { return this.itemHeight; }
      set
      {
        if (this.itemHeight == value)
          return;
        this.itemHeight = value;
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private FisheyeLayoutType itemLayoutType = FisheyeLayoutType.Bottom;
    /// <summary>
    /// 选项布局类型
    /// </summary>
    [DefaultValue(FisheyeLayoutType.Bottom)]
    [Description("选项布局类型")]
    public FisheyeLayoutType ItemLayoutType
    {
      get { return this.itemLayoutType; }
      set
      {
        if (this.itemLayoutType == value)
          return;
        this.itemLayoutType = value;
        this.InitializeItemLayout();
        this.Invalidate();
      }
    }

    private FisheyeBarExt.FisheyeItemCollection fisheyeItemCollection;
    /// <summary>
    /// 鱼眼菜单选项集合
    /// </summary>
    [DefaultValue(null)]
    [Description("鱼眼菜单选项集合")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public FisheyeBarExt.FisheyeItemCollection Items
    {
      get
      {
        if (this.fisheyeItemCollection == null)
          this.fisheyeItemCollection = new FisheyeBarExt.FisheyeItemCollection(this);
        return this.fisheyeItemCollection;
      }
    }

    protected override Size DefaultSize
    {
      get
      {
        return new Size(600, 128);
      }
    }

    #endregion

    public FisheyeBarExt()
    {
      SetStyle(ControlStyles.UserPaint, true);
      SetStyle(ControlStyles.AllPaintingInWmPaint, true);
      SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
      SetStyle(ControlStyles.SupportsTransparentBackColor, true);

      InitializeComponent();
      this.fisheyeItemCollection = new FisheyeItemCollection(this);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);

      Graphics g = e.Graphics;
      g.SmoothingMode = SmoothingMode.AntiAlias;
      RectangleF bounds_rect = g.ClipBounds;

      RectangleF rectf = new RectangleF(0, 0, this.ItemWidth, this.ItemHeight);
      SolidBrush itemtext_sb = new SolidBrush(this.ItemTextColor);
      for (int i = 0; i < this.fisheyeItemCollection.Count; i++)
      {
        if (this.Items[i].Image != null)
        {
          g.DrawImage(this.Items[i].Image, new RectangleF(this.fisheyeItemCollection[i].now_rectf.X, this.fisheyeItemCollection[i].now_rectf.Y, this.fisheyeItemCollection[i].now_rectf.Width, this.fisheyeItemCollection[i].now_rectf.Height));
        }
        if (this.ItemTextShow)
        {
          SizeF itemtext_size = g.MeasureString(this.fisheyeItemCollection[i].Text, this.ItemTextFont);
          g.DrawString(this.fisheyeItemCollection[i].Text, this.ItemTextFont, itemtext_sb, this.fisheyeItemCollection[i].now_rectf.X + (this.fisheyeItemCollection[i].now_rectf.Width - itemtext_size.Width) / 2f, this.fisheyeItemCollection[i].now_rectf.Bottom - itemtext_size.Height);
        }
      }
      itemtext_sb.Dispose();
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
      base.OnMouseMove(e);

      for (int i = 0; i < this.fisheyeItemCollection.Count; i++)
      {
        float distance = (float)Math.Sqrt(Math.Pow(Math.Abs(this.fisheyeItemCollection[i].now_centerpointf.X - e.X), 2) + Math.Pow(Math.Abs(this.fisheyeItemCollection[i].now_centerpointf.Y - e.Y), 2));
        float p = 1 - distance / 240;
        if (p < this.Proportion)
        {
          p = this.Proportion;
        }
        this.fisheyeItemCollection[i].now_proportion = p;
      }

      this.InitializeItemLayout();
      this.Invalidate();
    }

    protected override void OnMouseLeave(EventArgs e)
    {
      base.OnMouseLeave(e);

      for (int i = 0; i < this.fisheyeItemCollection.Count; i++)
      {
        this.InitializeItem(this.fisheyeItemCollection[i]);
      }

      this.InitializeItemLayout();
      this.Invalidate();
    }

    protected override void OnClick(EventArgs e)
    {
      base.OnClick(e);

      Point point = this.PointToClient(Control.MousePosition);
      if (this.fisheyeItemClick != null)
      {
        for (int i = 0; i < this.Items.Count; i++)
        {
          if (this.Items[i].now_rectf.Contains(point))
          {
            this.fisheyeItemClick(this, new FisheyeItemEventArgs() { Item = this.Items[i] });
            break;
          }
        }
      }
    }

    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);

      this.InitializeItemLayout();
      this.Invalidate();
    }

    /// <summary>
    ///初始化鱼眼菜单选项 
    /// </summary>
    /// <param name="item"></param>
    private void InitializeItem(FisheyeItem item)
    {
      item.now_proportion = this.Proportion;
    }

    /// <summary>
    ///初始化鱼眼菜单选项集合
    /// </summary>
    private void InitializeItems()
    {
      foreach (FisheyeItem item in this.fisheyeItemCollection)
      {
        item.now_proportion = this.Proportion;
      }
    }

    /// <summary>
    /// 初始化鱼眼菜单选项布局
    /// </summary>
    private void InitializeItemLayout()
    {
      float sum = 0f;
      for (int i = 0; i < this.fisheyeItemCollection.Count; i++)
      {
        float now_width = this.ItemWidth * this.fisheyeItemCollection[i].now_proportion;
        float now_height = this.ItemHeight * this.fisheyeItemCollection[i].now_proportion;
        this.fisheyeItemCollection[i].now_rectf = new RectangleF(0f, 0f, now_width, now_height);
        switch (this.ItemLayoutType)
        {
          case FisheyeLayoutType.Top:
          case FisheyeLayoutType.Bottom:
          case FisheyeLayoutType.HorizontalCenter:
            {
              sum += now_width;
              break;
            }
          case FisheyeLayoutType.Left:
          case FisheyeLayoutType.Right:
          case FisheyeLayoutType.VerticalCenter:
            {
              sum += now_height;
              break;
            }
        }
      }
      for (int i = 0; i < this.fisheyeItemCollection.Count; i++)
      {
        float x = 0;
        float y = 0;
        switch (this.ItemLayoutType)
        {
          case FisheyeLayoutType.Bottom:
            {
              x = (i == 0) ? (this.ClientRectangle.Width - sum) / 2f : this.fisheyeItemCollection[i - 1].now_rectf.Right;
              y = this.ClientRectangle.Height - this.fisheyeItemCollection[i].now_rectf.Height;
              break;
            }
          case FisheyeLayoutType.Top:
            {
              x = (i == 0) ? (this.ClientRectangle.Width - sum) / 2f : this.fisheyeItemCollection[i - 1].now_rectf.Right;
              y = 0;
              break;
            }

          case FisheyeLayoutType.HorizontalCenter:
            {
              x = (i == 0) ? (this.ClientRectangle.Width - sum) / 2f : this.fisheyeItemCollection[i - 1].now_rectf.Right;
              y = (this.ClientRectangle.Height - this.fisheyeItemCollection[i].now_rectf.Height) / 2;
              break;
            }
          case FisheyeLayoutType.Left:
            {
              x = 0;
              y = (i == 0) ? (this.ClientRectangle.Height - sum) / 2f : this.fisheyeItemCollection[i - 1].now_rectf.Bottom;
              break;
            }
          case FisheyeLayoutType.Right:
            {
              x = this.ClientRectangle.Right - this.fisheyeItemCollection[i].now_rectf.Width;
              y = (i == 0) ? (this.ClientRectangle.Height - sum) / 2f : this.fisheyeItemCollection[i - 1].now_rectf.Bottom;
              break;
            }
          case FisheyeLayoutType.VerticalCenter:
            {
              x = (this.ClientRectangle.Right - this.fisheyeItemCollection[i].now_rectf.Width) / 2;
              y = (i == 0) ? (this.ClientRectangle.Height - sum) / 2f : this.fisheyeItemCollection[i - 1].now_rectf.Bottom;
              break;
            }
        }
        this.fisheyeItemCollection[i].now_rectf = new RectangleF(x, y, this.fisheyeItemCollection[i].now_rectf.Width, this.fisheyeItemCollection[i].now_rectf.Height);
        this.fisheyeItemCollection[i].now_centerpointf = new PointF(this.fisheyeItemCollection[i].now_rectf.X + (this.fisheyeItemCollection[i].now_rectf.Width / 2), this.fisheyeItemCollection[i].now_rectf.Y + (this.fisheyeItemCollection[i].now_rectf.Height / 2));
      }
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    /// <summary>
    /// 鱼眼菜单选项集合
    /// </summary>
    [Description("鱼眼菜单选项集合")]
    [Editor(typeof(CollectionEditorExt), typeof(UITypeEditor))]
    public sealed class FisheyeItemCollection : IList, ICollection, IEnumerable
    {
      private ArrayList fisheyeItemList = new ArrayList();
      private FisheyeBarExt owner;

      public FisheyeItemCollection(FisheyeBarExt owner)
      {
        this.owner = owner;
      }

      #region IEnumerable

      public IEnumerator GetEnumerator()
      {
        FisheyeItem[] listArray = new FisheyeItem[this.fisheyeItemList.Count];
        for (int index = 0; index < listArray.Length; ++index)
          listArray[index] = (FisheyeItem)this.fisheyeItemList[index];
        return listArray.GetEnumerator();
      }

      #endregion

      #region ICollection

      public void CopyTo(Array array, int index)
      {
        for (int i = 0; i < this.Count; i++)
          array.SetValue(this.fisheyeItemList[i], i + index);
      }

      public int Count
      {
        get
        {
          return this.fisheyeItemList.Count;
        }
      }

      public bool IsSynchronized
      {
        get
        {
          return false;
        }
      }

      public object SyncRoot
      {
        get
        {
          return (object)this;
        }
      }

      #endregion

      #region IList

      public int Add(object value)
      {
        FisheyeItem fisheyeItem = (FisheyeItem)value;
        this.owner.InitializeItem(fisheyeItem);
        this.fisheyeItemList.Add(fisheyeItem);
        this.owner.InitializeItemLayout();
        this.owner.Invalidate();
        return this.Count - 1;
      }

      public void Clear()
      {
        this.fisheyeItemList.Clear();
        this.owner.InitializeItemLayout();
        this.owner.Invalidate();
      }

      public bool Contains(object value)
      {
        return this.IndexOf(value) != -1;
      }

      public int IndexOf(object value)
      {
        return this.fisheyeItemList.IndexOf(value);
      }

      public void Insert(int index, object value)
      {
        throw new NotImplementedException();
      }

      public bool IsFixedSize
      {
        get { return false; }
      }

      public bool IsReadOnly
      {
        get { return false; }
      }

      public void Remove(object value)
      {
        if (!(value is FisheyeItem))
          return;
        this.fisheyeItemList.Remove((FisheyeItem)value);
        this.owner.InitializeItemLayout();
        this.owner.Invalidate();
      }

      public void RemoveAt(int index)
      {
        this.fisheyeItemList.RemoveAt(index);
        this.owner.InitializeItemLayout();
        this.owner.Invalidate();
      }

      public FisheyeItem this[int index]
      {
        get
        {
          return (FisheyeItem)this.fisheyeItemList[index];
        }
        set
        {
          this.fisheyeItemList[index] = (FisheyeItem)value;
          this.owner.InitializeItemLayout();
          this.owner.Invalidate();
        }
      }

      object IList.this[int index]
      {
        get
        {
          return (object)this.fisheyeItemList[index];
        }
        set
        {
          this.fisheyeItemList[index] = (FisheyeItem)value;
          this.owner.InitializeItemLayout();
          this.owner.Invalidate();
        }
      }

      #endregion

    }

  }

  /// <summary>
  /// 鱼眼菜单选项
  /// </summary>
  [Description("鱼眼菜单选项")]
  public class FisheyeItem
  {
    /// <summary>
    /// 预留信息
    /// </summary>
    [Browsable(true)]
    [DefaultValue("")]
    [Description("预留信息")]
    public string Tag { get; set; }

    /// <summary>
    /// 选项图片
    /// </summary>
    [Browsable(true)]
    [DefaultValue(null)]
    [Description("选项图片")]
    public Image Image { get; set; }

    /// <summary>
    /// 文本信息
    /// </summary>
    [Browsable(true)]
    [DefaultValue("")]
    [Description("文本信息")]
    public string Text { get; set; }

    /// <summary>
    /// 当前选项大小比例
    /// </summary>
    [Browsable(false)]
    public float now_proportion { get; set; }

    /// <summary>
    /// 当前选项rectf
    /// </summary>
    [Browsable(false)]
    public RectangleF now_rectf { get; set; }

    /// <summary>
    /// 当前选项rectf中心坐标
    /// </summary>
    [Browsable(false)]
    public PointF now_centerpointf { get; set; }
  }

  /// <summary>
  /// 布局类型
  /// </summary>
  [Description("布局类型")]
  public enum FisheyeLayoutType
  {
    /// <summary>
    /// 靠上
    /// </summary>
    Top,
    /// <summary>
    /// 
    /// </summary>
    Left,
    /// <summary>
    /// 靠下
    /// </summary>
    Bottom,
    /// <summary>
    /// 靠右
    /// </summary>
    Right,
    /// <summary>
    /// 横向居中
    /// </summary>
    HorizontalCenter,
    /// <summary>
    /// 垂直居中
    /// </summary>
    VerticalCenter
  }

  /// <summary>
  /// 鱼眼菜单单击事件参数
  /// </summary>
  [Description("鱼眼菜单单击事件参数")]
  public class FisheyeItemEventArgs : EventArgs
  {
    /// <summary>
    /// 鱼眼菜单选项
    /// </summary>
    [Description("鱼眼菜单选项")]
    public FisheyeItem Item { get; set; }
  }

 

源码下载:仿MAC鱼眼菜单栏控件.zip

转载于:https://www.cnblogs.com/tlmbem/p/11314567.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值