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

时间: 2024-10-07 11:38:38

MAC鱼眼效果菜单控件----------WinForm控件开发系列的相关文章

GDI不规则圆弧菜单控件----------WinForm控件开发系列

/// <summary> /// 圆弧菜单控件 /// </summary> [ToolboxItem(true)] [DefaultProperty("Items")] [DefaultEvent("RadianMenuItemClick")] [Description("圆弧菜单控件")] public partial class RadianMenuExt : Control { public delegate v

走马灯图片轮播控件----------WinForm控件开发系列

/// <summary> /// 走马灯图片轮播控件 /// </summary> [ToolboxItem(true)] [DefaultProperty("Images")] [Description("走马灯图片轮播控件")] public partial class ImageCarouselExt : Control { #region private bool barShow = true; /// <summary>

数字时间控件----------WinForm控件开发系列

/// <summary> /// 数字时间控件 /// </summary> [ToolboxItem(true)] [DefaultProperty("Value")] [DefaultEvent("ValueChanged")] [Description("数字时间控件")] public partial class TimeExt : Control { public delegate void EventHand

按钮动画控件----------WinForm控件开发系列

public partial class ButtonExt : Button { private AnimationTimer _Animation; /// <summary> /// 动画组件对象 /// </summary> [Description("动画组件对象")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public AnimationT

雷达扫描控件----------WinForm控件开发系列

/// <summary> /// 雷达扫描控件 /// </summary> [ToolboxItem(true)] [DefaultProperty("Items")] [Description("雷达扫描控件")] public partial class RadarExt : Control { #region private Color areaColor = Color.LawnGreen; /// <summary>

TabPanel美化控件----------WinForm控件开发系列

/// <summary> /// TabControl /// </summary> [ToolboxItem(true)] [Description("TabControl")] public partial class TabControlExt : TabControl { #region private AnimationTimer animation; /// <summary> /// 动画组件对象 /// </summary&g

Chart实时段分析控件----------WinForm控件开发系列

/// <summary> /// 实时段进度控件 /// </summary> [ToolboxItem(true)] [Description("实时段进度控件")] public partial class ChartExt : Control { #region private Timer interval; /// <summary> /// 定时刷新 /// </summary> [Browsable(false)] [Des

加载等待控件----------WinForm控件开发系列

/// <summary> /// 加载进度控件 /// </summary> [ToolboxItem(true)] [Description("加载进度控件")] [DefaultProperty("Active")] public partial class LoadProgressExt : Control { #region 属性 private LoadProgressType progressType = LoadProgres

温度计控件----------WinForm控件开发系列

/// <summary> /// 温度计控件 /// </summary> [ToolboxItem(true)] [DefaultProperty("Value")] [DefaultEvent("ValueChanged")] [Description("温度计控件")] public partial class ThermometerExt : Control { public delegate void Even