using HotelPms.Share.Windows.GraphicsApi;
|
using HotelPms.Share.Windows.Util;
|
using System;
|
using System.Collections.Generic;
|
using System.Drawing;
|
using System.Drawing.Drawing2D;
|
using System.Windows.Forms;
|
using System.Windows.Forms.VisualStyles;
|
|
namespace HotelPms.Share.Windows.Component
|
{
|
public class TreeMenu : System.Windows.Forms.Control
|
{
|
#region ★★★★★ Declartions ★★★★★
|
|
public enum HitDownSquare : int
|
{
|
None = 0,
|
Left,
|
Right,
|
Tab,
|
}
|
|
public enum AngleStyle : int
|
{
|
/// <summary>
|
/// 直角
|
/// </summary>
|
Normal = 0,
|
/// <summary>
|
/// 円角
|
/// </summary>
|
Round = 1
|
}
|
|
public sealed class HitTestInfo
|
{
|
public static readonly HitTestInfo Nowhere;
|
|
internal int y;
|
internal int x;
|
internal int index = 0;
|
internal HitDownSquare type;
|
|
static HitTestInfo()
|
{
|
HitTestInfo.Nowhere = new HitTestInfo();
|
}
|
|
internal HitTestInfo()
|
{
|
this.type = HitDownSquare.None;
|
this.x = -1;
|
this.y = -1;
|
}
|
|
public int Index { get { return index; } }
|
|
public int X
|
{
|
get { return this.x; }
|
}
|
|
public int Y
|
{
|
get { return this.y; }
|
}
|
|
public HitDownSquare Type
|
{
|
get { return this.type; }
|
}
|
|
public override int GetHashCode()
|
{
|
return this.x << 16 | this.y << 8 | (int)this.type;
|
}
|
|
public override bool Equals(object obj)
|
{
|
HitTestInfo hi = obj as HitTestInfo;
|
return (this.type == hi.type && this.x == hi.x && this.x == hi.x);
|
}
|
|
public override string ToString()
|
{
|
return string.Concat(new string[7] { "{ ", this.type.ToString(), ",", this.x.ToString(), ",", this.y.ToString(), "}" });
|
}
|
}
|
|
|
public event CellFormatEventHandler CellFormat = null;
|
public event EventHandler SelectedIndexChanged = null;
|
|
private Rectangle m_LeftRect;
|
private Rectangle m_RightRect;
|
private List<Rectangle> m_TabRect = new List<Rectangle>();
|
private StringFormat m_StringFormat = new StringFormat(StringFormatFlags.NoWrap);
|
private int m_TabCount = 3;
|
private int m_FocusIndex = -1;
|
private bool m_IsMouseDown = false;
|
|
#endregion
|
|
#region ★★★★★ Property ★★★★★
|
|
//private int m_LastMouseClickIndex = -1;
|
//public int LastMouseClickIndex
|
//{
|
// get { return m_LastMouseClickIndex; }
|
// set { m_LastMouseClickIndex = value; }
|
//}
|
|
private bool m_FirstColFrozen = false;
|
public bool FirstColFrozen
|
{
|
get { return m_FirstColFrozen; }
|
set { m_FirstColFrozen = value; }
|
}
|
|
private Color m_SelectBorderColor = Color.FromArgb(255, 86, 157, 229);
|
|
public Color SelectBorderColor
|
{
|
get { return m_SelectBorderColor; }
|
set { m_SelectBorderColor = value; }
|
}
|
|
private Color m_FocusBackColorMax = Color.FromArgb(255, 228, 240, 252);
|
|
public Color FocusBackColorMax
|
{
|
get { return m_FocusBackColorMax; }
|
set { m_FocusBackColorMax = value; }
|
}
|
private Color m_FocusBackColorMin = Color.FromArgb(255, 234, 243, 252);
|
|
public Color FocusBackColorMin
|
{
|
get { return m_FocusBackColorMin; }
|
set { m_FocusBackColorMin = value; }
|
}
|
|
private Color m_MouseDownBackColorMax = Color.FromArgb(255, 207, 230, 252);
|
|
public Color MouseDownBackColorMax
|
{
|
get { return m_MouseDownBackColorMax; }
|
set { m_MouseDownBackColorMax = value; }
|
}
|
private Color m_MouseDownBackColorMin = Color.FromArgb(255, 217, 235, 252);
|
|
public Color MouseDownBackColorMin
|
{
|
get { return m_MouseDownBackColorMin; }
|
set { m_MouseDownBackColorMin = value; }
|
}
|
|
/// <summary>
|
/// 表示タブの数
|
/// </summary>
|
public int TabCount
|
{
|
get { return m_TabCount; }
|
set { m_TabCount = value; Invalidate(); }
|
}
|
|
private int m_ScrollButtonWidth = 35;
|
|
/// <summary>
|
/// 浸り右
|
/// </summary>
|
public int ScrollButtonWidth
|
{
|
get { return m_ScrollButtonWidth; }
|
set { m_ScrollButtonWidth = value; Invalidate(); }
|
}
|
|
private Color m_ScrollButtonBackColorMax = Color.FromArgb(255, 86, 157, 229);
|
|
public Color ScrollButtonBackColorMax
|
{
|
get { return m_ScrollButtonBackColorMax; }
|
set { m_ScrollButtonBackColorMax = value; Invalidate(); }
|
}
|
|
private Color m_ScrollButtonBackColorMin = Color.FromArgb(255, 229, 240, 251);
|
|
public Color ScrollButtonBackColorMin
|
{
|
get { return m_ScrollButtonBackColorMin; }
|
set { m_ScrollButtonBackColorMin = value; Invalidate(); }
|
}
|
|
private Color m_ScrollButtonForeColor = Color.Black;
|
|
public Color ScrollButtonForeColor
|
{
|
get { return m_ScrollButtonForeColor; }
|
set { m_ScrollButtonForeColor = value; Invalidate(); }
|
}
|
private Image m_ScrollButtonImage = null;
|
|
public Image ScrollButtonImage
|
{
|
get { return m_ScrollButtonImage; }
|
set { m_ScrollButtonImage = value; Invalidate(); }
|
}
|
|
private string m_ScrollLeftText = "<<";
|
|
public string ScrollLeftText
|
{
|
get { return m_ScrollLeftText; }
|
set { m_ScrollLeftText = value; Invalidate(); }
|
}
|
|
private string m_ScrollRightText = ">>";
|
|
public string ScrollRightText
|
{
|
get { return m_ScrollRightText; }
|
set { m_ScrollRightText = value; Invalidate(); }
|
}
|
|
private List<string> m_TabKeyList = new List<string>();
|
|
//public List<string> TabKeyList
|
//{
|
// get { return m_TabKeyList; }
|
// set { m_TabKeyList = value; }
|
//}
|
private List<string> m_TabTextList = new List<string>();
|
|
//public List<string> TabTextList
|
//{
|
// get { return m_TabTextList; }
|
// set { m_TabTextList = value; }
|
//}
|
private int m_SelectIndex = 0;
|
|
public int SelectIndex
|
{
|
get { return m_SelectIndex; }
|
set
|
{
|
m_SelectIndex = value;
|
if(m_TabKeyList.Count > 0 && m_TabCount > 0)
|
{
|
if (m_SelectIndex < m_TopIndex) { m_TopIndex = (m_SelectIndex - 1 < 0) ? 0 : (m_SelectIndex - 1); }
|
if ((m_TopIndex + m_TabCount - 1) < m_SelectIndex)
|
{
|
m_TopIndex = m_SelectIndex - m_TabCount + 2;
|
if ((m_TopIndex + m_TabCount - 1) > (m_TabKeyList.Count - 1)) { m_TopIndex = m_SelectIndex - m_TabCount + 1; }
|
}
|
if ((m_TopIndex + m_TabCount - 1) == m_SelectIndex && m_SelectIndex < (m_TabKeyList.Count - 1)) { m_TopIndex++; }
|
}
|
Invalidate();
|
}
|
}
|
|
public string SelectKey
|
{
|
get { return m_TabKeyList.Count == 0 ? string.Empty : m_TabKeyList[m_SelectIndex]; }
|
}
|
|
public int DataCount
|
{
|
get { return m_TabKeyList.Count; }
|
}
|
|
private Color m_SelectBackColorMin = SystemColors.Control;
|
|
public Color SelectBackColorMin
|
{
|
get { return m_SelectBackColorMin; }
|
set { m_SelectBackColorMin = value; Invalidate(); }
|
}
|
|
private Color m_SelectBackColorMax = SystemColors.Highlight;
|
|
public Color SelectBackColorMax
|
{
|
get { return m_SelectBackColorMax; }
|
set { m_SelectBackColorMax = value; Invalidate(); }
|
}
|
private Color m_SelectForeColor = SystemColors.HighlightText;
|
|
public Color SelectForeColor
|
{
|
get { return m_SelectForeColor; }
|
set { m_SelectForeColor = value; Invalidate(); }
|
}
|
private int m_TabSpace = 2;
|
|
public int TabSpace
|
{
|
get { return m_TabSpace; }
|
set { m_TabSpace = value; Invalidate(); }
|
}
|
private Color m_TabBackColorMax = Color.FromArgb(255, 86, 157, 229);
|
|
public Color TabBackColorMax
|
{
|
get { return m_TabBackColorMax; }
|
set { m_TabBackColorMax = value; Invalidate(); }
|
}
|
|
private Color m_TabBackColorMin = Color.FromArgb(255, 229, 240, 251);
|
|
public Color TabBackColorMin
|
{
|
get { return m_TabBackColorMin; }
|
set { m_TabBackColorMin = value; Invalidate(); }
|
}
|
|
private Color m_TabForeColor = Color.Black;
|
|
public Color TabForeColor
|
{
|
get { return m_TabForeColor; }
|
set { m_TabForeColor = value; Invalidate(); }
|
}
|
|
private Color m_BorderColor = VisualStyleInformation.TextControlBorder;
|
|
public Color BorderColor
|
{
|
get { return m_BorderColor; }
|
set { m_BorderColor = value; Invalidate(); }
|
}
|
private AngleStyle m_TabStyle = AngleStyle.Normal; //0.直 1.円
|
|
public AngleStyle TabStyle
|
{
|
get { return m_TabStyle; }
|
set { m_TabStyle = value; Invalidate(); }
|
}
|
|
private int m_CornerRadius = 10;
|
|
public int CornerRadius
|
{
|
get { return m_CornerRadius; }
|
set { m_CornerRadius = value; Invalidate(); }
|
}
|
|
private int m_TopIndex = 0;
|
|
public int TopIndex
|
{
|
get { return m_TopIndex; }
|
set { m_TopIndex = value; Invalidate(); }
|
}
|
|
#endregion
|
|
#region ★★★★★ Class Event ★★★★★
|
|
public TreeMenu()
|
{
|
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.Opaque | ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.Selectable | ControlStyles.UserMouse, true);
|
m_StringFormat.Alignment = StringAlignment.Center;
|
m_StringFormat.LineAlignment = StringAlignment.Center;
|
}
|
|
protected override void Dispose(bool disposing)
|
{
|
m_StringFormat.Dispose();
|
base.Dispose(disposing);
|
}
|
|
#endregion
|
|
#region ★★★★★ Control Event ★★★★★
|
|
protected override void OnPaint(PaintEventArgs e)
|
{
|
base.OnPaint(e);
|
|
try
|
{
|
GdiPlus.FillRectangle(e.Graphics, BackColor, ClientRectangle);
|
|
if (m_TabCount <= 0 || m_TabKeyList.Count == 0 || m_TabTextList.Count == 0)
|
{
|
return;
|
}
|
|
//余白取る
|
Rectangle allRect = new Rectangle(ClientRectangle.X + this.Margin.Left, ClientRectangle.Y + this.Margin.Top,
|
ClientRectangle.Width - this.Margin.Left - this.Margin.Right, ClientRectangle.Height - this.Margin.Top - this.Margin.Bottom);
|
|
//描く領域の確定
|
bool showScroll = (m_TabKeyList.Count > m_TabCount);
|
if (showScroll)
|
{
|
m_RightRect = new Rectangle(ClientRectangle.Width - (m_ScrollButtonWidth + this.Margin.Right), allRect.Y, m_ScrollButtonWidth, allRect.Height);
|
DrawCell(e.Graphics, m_RightRect, m_ScrollRightText, m_ScrollButtonBackColorMin, m_ScrollButtonBackColorMax, m_ScrollButtonForeColor, m_ScrollButtonForeColor, false, m_FocusIndex == -3);
|
|
m_LeftRect = new Rectangle(ClientRectangle.Width - m_ScrollButtonWidth * 2 - m_TabSpace - this.Margin.Right, allRect.Y, m_ScrollButtonWidth, allRect.Height);
|
DrawCell(e.Graphics, m_LeftRect, m_ScrollLeftText, m_ScrollButtonBackColorMin, m_ScrollButtonBackColorMax, m_ScrollButtonForeColor, m_ScrollButtonForeColor, false, m_FocusIndex == -2);
|
}
|
|
m_TabRect.Clear();
|
int tabWidth = allRect.Width - (showScroll ? (m_ScrollButtonWidth * 2 + m_TabSpace) : 0);
|
int tabCellWidth = (tabWidth - m_TabSpace * m_TabCount) / m_TabCount;
|
int x = allRect.X;
|
for (int i = 0; i < m_TabCount; i++)
|
{
|
if ((m_TopIndex + i) > (m_TabTextList.Count - 1)) { break; }
|
m_TabRect.Add(new Rectangle(x, allRect.Y, tabCellWidth, allRect.Height));
|
|
int dataIndex = (m_FirstColFrozen && i == 0) ? 0 : (m_TopIndex + i);
|
TabMarkFormatEventArgs eventArgs = new TabMarkFormatEventArgs(false, null, m_TabForeColor, m_SelectForeColor, m_TabKeyList[dataIndex]);
|
if (CellFormat != null)
|
{
|
CellFormat(this, eventArgs);
|
if (eventArgs.Cancel) { continue; }
|
}
|
|
DrawCell(e.Graphics, m_TabRect[i], m_TabTextList[dataIndex], m_TabBackColorMin, m_TabBackColorMax, eventArgs.TabForeColor, eventArgs.TabSelForeColor, m_SelectIndex == (m_TopIndex + i), m_FocusIndex == i);
|
x += (tabCellWidth + m_TabSpace);
|
}
|
}
|
catch
|
{
|
}
|
}
|
|
protected override void OnMouseWheel(MouseEventArgs e)
|
{
|
if (e.Delta > 0)
|
{
|
if (m_TabKeyList.Count - m_TopIndex > m_TabCount) { m_TopIndex++; }
|
}
|
else
|
{
|
if (m_TopIndex > 0) { m_TopIndex--; }
|
}
|
base.OnMouseWheel(e);
|
Invalidate();
|
}
|
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
{
|
if (keyData == Keys.Tab)
|
return true;
|
if (keyData == (Keys.Tab | Keys.Shift))
|
return true;
|
|
int orgIndex = m_SelectIndex;
|
switch (keyData)
|
{
|
case Keys.Left:
|
if (m_SelectIndex > 0) { m_SelectIndex--; }
|
if (m_SelectIndex == 0)
|
{
|
m_TopIndex = 0;
|
}
|
else if (m_SelectIndex == m_TopIndex)
|
{
|
m_TopIndex--;
|
}
|
if (orgIndex != m_SelectIndex)
|
{
|
Invalidate();
|
if (SelectedIndexChanged != null) { SelectedIndexChanged(this, new EventArgs()); }
|
}
|
return true;
|
case Keys.Right:
|
if (m_SelectIndex < (m_TabKeyList.Count - 1)) { m_SelectIndex++; }
|
if (m_SelectIndex == (m_TopIndex + m_TabCount - 1) && m_SelectIndex < (m_TabKeyList.Count - 1))
|
{
|
m_TopIndex++;
|
}
|
if (orgIndex != m_SelectIndex)
|
{
|
Invalidate();
|
if (SelectedIndexChanged != null) { SelectedIndexChanged(this, new EventArgs()); }
|
}
|
return true;
|
}
|
|
|
return base.ProcessCmdKey(ref msg, keyData);
|
}
|
|
protected override void OnMouseClick(MouseEventArgs e)
|
{
|
base.OnMouseClick(e);
|
|
HitTestInfo item = HitTest(e.X, e.Y);
|
if (item.Type == HitDownSquare.Tab)
|
{
|
int orgIndex = m_SelectIndex;
|
|
if (m_FirstColFrozen && item.Index == 0)
|
{
|
m_SelectIndex = 0;
|
}
|
else
|
{
|
m_SelectIndex = m_TopIndex + item.Index;
|
|
if ((item.Index + 1) == m_TabCount && m_SelectIndex < (m_TabKeyList.Count - 1))
|
{
|
//最後へ
|
m_TopIndex++;
|
}
|
else if (item.Index == 0 && m_SelectIndex != 0)
|
{
|
m_TopIndex--;
|
}
|
}
|
//m_LastMouseClickIndex = item.Index;
|
|
Invalidate();
|
if (orgIndex != m_SelectIndex)
|
{
|
if (SelectedIndexChanged != null) { SelectedIndexChanged(this, new EventArgs()); }
|
}
|
}
|
else if (item.Type == HitDownSquare.Left)
|
{
|
if (m_TopIndex > 0) { m_TopIndex--; }
|
}
|
else if (item.Type == HitDownSquare.Right)
|
{
|
if (m_TabKeyList.Count - m_TopIndex > m_TabCount) { m_TopIndex++; }
|
}
|
}
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
{
|
HitTestInfo item = HitTest(e.X, e.Y);
|
m_FocusIndex = -1;
|
if (item.Type == HitDownSquare.Tab)
|
{
|
m_FocusIndex = item.Index;
|
}
|
else if (item.Type == HitDownSquare.Left)
|
{
|
m_FocusIndex = -2;
|
}
|
else if (item.Type == HitDownSquare.Right)
|
{
|
m_FocusIndex = -3;
|
}
|
|
Invalidate();
|
base.OnMouseMove(e);
|
}
|
|
protected override void OnMouseLeave(System.EventArgs e)
|
{
|
//HitTestInfo item = HitTest(MousePosition.X, MousePosition.Y);
|
m_FocusIndex = -1;
|
Invalidate();
|
base.OnMouseLeave(e);
|
}
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
{
|
m_IsMouseDown = true;
|
Invalidate();
|
base.OnMouseDown(e);
|
}
|
|
protected override void OnMouseUp(MouseEventArgs e)
|
{
|
m_IsMouseDown = false;
|
Invalidate();
|
base.OnMouseUp(e);
|
}
|
|
protected override void OnResize(System.EventArgs e)
|
{
|
Invalidate();
|
base.OnResize(e);
|
}
|
|
#endregion
|
|
#region ★★★★★ Private Function ★★★★★
|
|
private void DrawCell(Graphics g, Rectangle ClientRectangle, string text, Color minBackColor, Color maxBackColor, Color foreColor, Color selForeColor, bool isSel, bool isFocus)
|
{
|
bool newflag = false;
|
|
//背景
|
Color bColorMax = isFocus ? (m_IsMouseDown ? m_MouseDownBackColorMax : (isSel ? ControlPaint.Light(m_SelectBackColorMin) : m_FocusBackColorMin)) : (isSel ? m_SelectBackColorMin : minBackColor);
|
Color bColorMin = isFocus ? (m_IsMouseDown ? m_MouseDownBackColorMin : (isSel ? ControlPaint.Light(m_SelectBackColorMax) : m_FocusBackColorMax)) : (isSel ? m_SelectBackColorMax : maxBackColor);
|
using (LinearGradientBrush lgBrush = new LinearGradientBrush(ClientRectangle, bColorMax, bColorMin, LinearGradientMode.Vertical))
|
{
|
lgBrush.SetSigmaBellShape(0.4f, 0.45f); //创建基于钟形曲线的渐变过渡过程。
|
|
if (m_TabStyle == AngleStyle.Round)
|
{
|
GdiPlus.FillRoundRectangle(g, lgBrush, ClientRectangle, m_CornerRadius);
|
}
|
else
|
{
|
g.FillRectangle(lgBrush, ClientRectangle);
|
}
|
}
|
|
//枠線
|
Color bColor = (isFocus || isSel) ? m_SelectBorderColor : m_BorderColor;
|
newflag = bColor.IsSystemColor;
|
Pen pen = newflag ? SystemPens.FromSystemColor(bColor) : new Pen(bColor);
|
if (m_TabStyle == AngleStyle.Round)
|
{
|
GdiPlus.DrawRoundRectangle(g, pen, ClientRectangle, m_CornerRadius);
|
}
|
else
|
{
|
g.DrawRectangle(pen, ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
|
}
|
if (!newflag) { pen.Dispose(); }
|
|
//文言
|
newflag = foreColor.IsSystemColor;
|
Color brushColor = isFocus ? (isSel ? ControlPaint.Light(selForeColor) : ControlPaint.Light(foreColor)) : (isSel ? selForeColor : foreColor);
|
SolidBrush brush = newflag ? SystemBrushes.FromSystemColor(brushColor) as SolidBrush : new SolidBrush(brushColor);
|
if (isSel)
|
{
|
using (Font f = new Font(this.Font, FontStyle.Bold)) { g.DrawString(text, f, brush, ClientRectangle, m_StringFormat); }
|
}
|
else
|
{
|
g.DrawString(text, this.Font, brush, ClientRectangle, m_StringFormat);
|
}
|
if (!newflag) { brush.Dispose(); }
|
}
|
|
|
#endregion
|
|
#region ★★★★★ Public Function ★★★★★
|
|
public HitTestInfo HitTest(int x, int y)
|
{
|
HitTestInfo hit = new HitTestInfo();
|
hit.x = x;
|
hit.y = y;
|
|
if (m_LeftRect.Contains(x, y))
|
{
|
hit.type = HitDownSquare.Left;
|
return hit;
|
}
|
|
if (m_RightRect.Contains(x, y))
|
{
|
hit.type = HitDownSquare.Right;
|
return hit;
|
}
|
|
for (int i = 0; i < m_TabRect.Count; i++)
|
{
|
if (m_TabRect[i].Contains(x, y))
|
{
|
hit.type = HitDownSquare.Tab;
|
hit.index = i;
|
return hit;
|
}
|
}
|
|
return HitTestInfo.Nowhere;
|
}
|
|
public void AddItem(string key, string text)
|
{
|
m_TabKeyList.Add(key);
|
m_TabTextList.Add(text);
|
Invalidate();
|
}
|
|
public void Clear()
|
{
|
m_FocusIndex = -1;
|
m_SelectIndex = 0;
|
m_TopIndex = 0;
|
m_TabKeyList.Clear();
|
m_TabTextList.Clear();
|
Invalidate();
|
}
|
|
public void RemoveItem(string key)
|
{
|
int index = m_TabKeyList.IndexOf(key);
|
if (index >= 0) { RemoveItem(index); }
|
}
|
|
public void RemoveItem(int index)
|
{
|
m_TabKeyList.RemoveAt(index);
|
m_TabTextList.RemoveAt(index);
|
Invalidate();
|
}
|
|
public void SetIndexByKey(string key)
|
{
|
for (int i = 0; i < m_TabKeyList.Count; i++)
|
{
|
if (m_TabKeyList[i] == key)
|
{
|
SelectIndex = i;
|
break;
|
}
|
}
|
}
|
|
public string GetKey(int index)
|
{
|
return m_TabKeyList.Count == 0 ? string.Empty : m_TabKeyList[index];
|
}
|
|
public string GetText(int index)
|
{
|
return m_TabTextList.Count == 0 ? string.Empty : m_TabTextList[index];
|
}
|
|
#endregion
|
}
|
}
|