// ***********************************************************************
// Assembly : HZH_Controls
// Created : 2019-10-08
//
// ***********************************************************************
//
// Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
//
//
// Blog: https://www.cnblogs.com/bfyx
// GitHub:https://github.com/kwwwvagaa/NetWinformControl
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using HZH_Controls.Forms;
namespace HZH_Controls.Controls
{
///
/// Class UCNavigationMenu.
/// Implements the
///
///
[DefaultEvent("ClickItemed")]
public partial class UCNavigationMenu : UserControl
{
///
/// Occurs when [click itemed].
///
[Description("点击节点事件"), Category("自定义")]
public event EventHandler ClickItemed;
///
/// The select item
///
private NavigationMenuItem selectItem = null;
///
/// Gets the select item.
///
/// The select item.
[Description("选中的节点"), Category("自定义")]
public NavigationMenuItem SelectItem
{
get { return selectItem; }
private set { selectItem = value; }
}
///
/// The items
///
NavigationMenuItem[] items;
///
/// Gets or sets the items.
///
/// The items.
[Description("节点列表"), Category("自定义")]
public NavigationMenuItem[] Items
{
get { return items; }
set
{
items = value;
ReloadMenu();
}
}
///
/// The tip color
///
private Color tipColor = Color.FromArgb(255, 87, 34);
///
/// Gets or sets the color of the tip.
///
/// The color of the tip.
[Description("角标颜色"), Category("自定义")]
public Color TipColor
{
get { return tipColor; }
set { tipColor = value; }
}
///
/// 获取或设置控件的前景色。
///
/// The color of the fore.
///
///
///
public override System.Drawing.Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
foreach (Control c in this.Controls)
{
c.ForeColor = value;
}
}
}
///
/// 获取或设置控件显示的文字的字体。
///
/// The font.
///
///
///
///
///
///
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
foreach (Control c in this.Controls)
{
c.Font = value;
}
}
}
///
/// The m LST anchors
///
Dictionary m_lstAnchors = new Dictionary();
///
/// Initializes a new instance of the class.
///
public UCNavigationMenu()
{
InitializeComponent();
items = new NavigationMenuItem[0];
if (ControlHelper.IsDesignMode())
{
items = new NavigationMenuItem[4];
for (int i = 0; i < 4; i++)
{
items[i] = new NavigationMenuItem()
{
Text = "菜单" + (i + 1),
AnchorRight = i >= 2
};
}
}
}
///
/// Reloads the menu.
///
private void ReloadMenu()
{
try
{
ControlHelper.FreezeControl(this, true);
this.Controls.Clear();
if (items != null && items.Length > 0)
{
foreach (var item in items)
{
var menu = (NavigationMenuItem)item;
Label lbl = new Label();
lbl.AutoSize = false;
lbl.TextAlign = ContentAlignment.MiddleCenter;
lbl.Width = menu.ItemWidth;
lbl.Text = menu.Text;
lbl.Font = Font;
lbl.ForeColor = ForeColor;
lbl.Paint += lbl_Paint;
lbl.MouseEnter += lbl_MouseEnter;
lbl.Tag = menu;
lbl.Click += lbl_Click;
if (menu.AnchorRight)
{
lbl.Dock = DockStyle.Right;
}
else
{
lbl.Dock = DockStyle.Left;
}
this.Controls.Add(lbl);
lbl.BringToFront();
}
}
}
finally
{
ControlHelper.FreezeControl(this, false);
}
}
///
/// Handles the Click event of the lbl control.
///
/// The source of the event.
/// The instance containing the event data.
void lbl_Click(object sender, EventArgs e)
{
Label lbl = sender as Label;
if (lbl.Tag != null)
{
var menu = (NavigationMenuItem)lbl.Tag;
if (menu.Items == null || menu.Items.Length <= 0)
{
selectItem = menu;
while (m_lstAnchors.Count > 0)
{
try
{
foreach (var item in m_lstAnchors)
{
item.Value.Close();
m_lstAnchors.Remove(item.Key);
}
}
catch { }
}
if (ClickItemed != null)
{
ClickItemed(this, e);
}
}
else
{
CloseList(menu);
if (m_lstAnchors.ContainsKey(menu))
{
if (m_lstAnchors[menu] != null && !m_lstAnchors[menu].IsDisposed)
{
m_lstAnchors[menu].Close();
}
m_lstAnchors.Remove(menu);
}
ShowMoreMenu(lbl);
}
}
}
///
/// Handles the MouseEnter event of the lbl control.
///
/// The source of the event.
/// The instance containing the event data.
void lbl_MouseEnter(object sender, EventArgs e)
{
Label lbl = sender as Label;
ShowMoreMenu(lbl);
}
///
/// Checks the show.
///
/// The menu.
/// true if XXXX, false otherwise.
private bool CheckShow(NavigationMenuItem menu)
{
//检查已经打开的节点
if (m_lstAnchors.ContainsKey(menu))
{
CloseList(menu);
return false;
}
if (HasInCacheChild(menu))
{
if (m_lstAnchors.ContainsKey(menu.ParentItem))
{
CloseList(menu.ParentItem);
return true;
}
return false;
}
else
{
for (int i = 0; i < 1; )
{
try
{
foreach (var item in m_lstAnchors)
{
if (m_lstAnchors[item.Key] != null && !m_lstAnchors[item.Key].IsDisposed)
{
m_lstAnchors[item.Key].Close();
}
}
}
catch
{
continue;
}
i++;
}
m_lstAnchors.Clear();
return true;
}
}
///
/// Determines whether [has in cache child] [the specified menu].
///
/// The menu.
/// true if [has in cache child] [the specified menu]; otherwise, false.
private bool HasInCacheChild(NavigationMenuItem menu)
{
foreach (var item in m_lstAnchors)
{
if (item.Key == menu)
{
return true;
}
else
{
if (item.Key.Items != null)
{
if (item.Key.Items.Contains(menu))
return true;
}
}
}
return false;
}
///
/// Closes the list.
///
/// The menu.
private void CloseList(NavigationMenuItem menu)
{
if (menu.Items != null)
{
foreach (var item in menu.Items)
{
CloseList(item);
if (m_lstAnchors.ContainsKey(item))
{
if (m_lstAnchors[item] != null && !m_lstAnchors[item].IsDisposed)
{
m_lstAnchors[item].Close();
m_lstAnchors[item] = null;
m_lstAnchors.Remove(item);
}
}
}
}
}
///
/// Shows the more menu.
///
/// The label.
private void ShowMoreMenu(Label lbl)
{
var menu = (NavigationMenuItem)lbl.Tag;
if (CheckShow(menu))
{
if (menu.Items != null && menu.Items.Length > 0)
{
Panel panel = new Panel();
panel.BackColor = Color.White;
panel.Paint += panel_Paint;
panel.Padding = new System.Windows.Forms.Padding(1);
Size size = GetItemsSize(menu.Items);
var height = size.Height * menu.Items.Length + 2;
height += menu.Items.Count(p => p.HasSplitLintAtTop);//分割线
if (size.Width < lbl.Width)
size.Width = lbl.Width;
panel.Size = new Size(size.Width, height);
foreach (var item in menu.Items)
{
if (item.HasSplitLintAtTop)
{
UCSplitLine_H line = new UCSplitLine_H();
line.Dock = DockStyle.Top;
panel.Controls.Add(line);
line.BringToFront();
}
Label _lbl = new Label();
_lbl.Font = Font;
_lbl.ForeColor = this.BackColor;
_lbl.AutoSize = false;
_lbl.TextAlign = ContentAlignment.MiddleCenter;
_lbl.Height = size.Height;
_lbl.Text = item.Text;
_lbl.Dock = DockStyle.Top;
_lbl.BringToFront();
_lbl.Paint += lbl_Paint;
_lbl.MouseEnter += lbl_MouseEnter;
_lbl.Tag = item;
_lbl.Click += lbl_Click;
_lbl.Size = new System.Drawing.Size(size.Width, size.Height);
panel.Controls.Add(_lbl);
_lbl.BringToFront();
}
Point point = Point.Empty;
if (menu.ParentItem != null)
{
Point p = lbl.Parent.PointToScreen(lbl.Location);
if (p.X + lbl.Width + panel.Width > Screen.PrimaryScreen.Bounds.Width)
{
point = new Point(-1 * panel.Width - 2, -1 * lbl.Height);
}
else
{
point = new Point(panel.Width + 2, -1 * lbl.Height);
}
}
m_lstAnchors[menu] = new FrmAnchor(lbl, panel, point);
m_lstAnchors[menu].FormClosing += UCNavigationMenu_FormClosing;
m_lstAnchors[menu].Show(this);
m_lstAnchors[menu].Size = new Size(size.Width, height);
}
}
}
///
/// Handles the FormClosing event of the UCNavigationMenu control.
///
/// The source of the event.
/// The instance containing the event data.
void UCNavigationMenu_FormClosing(object sender, FormClosingEventArgs e)
{
FrmAnchor frm = sender as FrmAnchor;
if (m_lstAnchors.ContainsValue(frm))
{
foreach (var item in m_lstAnchors)
{
if (item.Value == frm)
{
m_lstAnchors.Remove(item.Key);
return;
}
}
}
}
///
/// Handles the Paint event of the panel control.
///
/// The source of the event.
/// The instance containing the event data.
void panel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SetGDIHigh();
Rectangle rect = new Rectangle(0, 0, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
var path = rect.CreateRoundedRectanglePath(2);
e.Graphics.DrawPath(new Pen(new SolidBrush(LineColors.Light)), path);
}
///
/// Gets the size of the items.
///
/// The items.
/// Size.
private Size GetItemsSize(NavigationMenuItem[] items)
{
Size size = Size.Empty;
if (items != null && items.Length > 0)
{
using (var g = this.CreateGraphics())
{
foreach (NavigationMenuItem item in items)
{
var s = g.MeasureString(item.Text, Font);
if (s.Width + 25 > size.Width)
{
size.Width = (int)s.Width + 25;
}
if (s.Height + 10 > size.Height)
{
size.Height = (int)s.Height + 10;
}
}
}
}
return size;
}
///
/// Handles the Paint event of the lbl control.
///
/// The source of the event.
/// The instance containing the event data.
void lbl_Paint(object sender, PaintEventArgs e)
{
Label lbl = sender as Label;
if (lbl.Tag != null)
{
var menu = (NavigationMenuItem)lbl.Tag;
e.Graphics.SetGDIHigh();
if (menu.ParentItem == null)//顶级节点支持图标和角标
{
if (menu.ShowTip)
{
if (!string.IsNullOrEmpty(menu.TipText))
{
var rect = new Rectangle(lbl.Width - 25, lbl.Height / 2 - 10, 20, 20);
var path = rect.CreateRoundedRectanglePath(5);
e.Graphics.FillPath(new SolidBrush(tipColor), path);
e.Graphics.DrawString(menu.TipText, new Font("微软雅黑", 8f), new SolidBrush(Color.White), rect, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
}
else
{
e.Graphics.FillEllipse(new SolidBrush(tipColor), new Rectangle(lbl.Width - 20, lbl.Height / 2 - 10, 10, 10));
}
}
if (menu.Icon != null)
{
e.Graphics.DrawImage(menu.Icon, new Rectangle(1, (lbl.Height - 25) / 2, 25, 25), 0, 0, menu.Icon.Width, menu.Icon.Height, GraphicsUnit.Pixel);
}
}
if (menu.ParentItem != null && menu.Items != null && menu.Items.Length > 0)
{
ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(this.BackColor), new Point(lbl.Width - 11, (lbl.Height - 5) / 2), 5, GraphDirection.Rightward);
}
}
}
}
}