
/// <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.InitializeLayout();
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.InitializeLayout();
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.InitializeLayout();
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.InitializeLayout();
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.InitializeLayout();
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.InitializeLayout();
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.InitializeLayout();
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;
SmoothingMode sm = g.SmoothingMode;
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);
}
}
g.SmoothingMode = sm;
}
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.InitializeLayout();
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.InitializeLayout();
this.Invalidate();
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
Point point = this.PointToClient(MousePosition);
if (this.fisheyeItemClick != null)
{
for (int i = 0; i < this.fisheyeItemCollection.Count; i++)
{
if (this.fisheyeItemCollection[i].now_rectf.Contains(point))
{
this.fisheyeItemClick(this, new FisheyeItemEventArgs() { item = this.fisheyeItemCollection[i] });
break;
}
}
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.InitializeLayout();
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 InitializeLayout()
{
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>
[Editor(typeof(CollectionEditor), 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)
{
throw new NotImplementedException();
}
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.InitializeLayout();
this.owner.Invalidate();
return this.Count - 1;
}
public void Clear()
{
this.fisheyeItemList.Clear();
this.owner.InitializeLayout();
this.owner.Invalidate();
}
public bool Contains(object value)
{
throw new NotImplementedException();
}
public int IndexOf(object value)
{
return this.IndexOf((FisheyeItem)value);
return -1;
}
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)
{
this.fisheyeItemList.Remove((FisheyeItem)value);
this.owner.InitializeLayout();
this.owner.Invalidate();
}
public void RemoveAt(int index)
{
this.fisheyeItemList.RemoveAt(index);
this.owner.InitializeLayout();
this.owner.Invalidate();
}
public FisheyeItem this[int index]
{
get
{
return (FisheyeItem)this.fisheyeItemList[index];
}
set
{
this.fisheyeItemList[index] = (FisheyeItem)value;
this.owner.InitializeLayout();
this.owner.Invalidate();
}
}
object IList.this[int index]
{
get
{
return (object)this.fisheyeItemList[index];
}
set
{
this.fisheyeItemList[index] = (FisheyeItem)value;
this.owner.InitializeLayout();
this.owner.Invalidate();
}
}
#endregion
}
}
源码下载:仿MAC鱼眼菜单栏控件.zip