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 TabMark : System.Windows.Forms.Control
{
#region ★★★★★ Declartions ★★★★★
public enum HitDownSquare : int
{
None = 0,
Left,
Right,
Tab,
}
public enum AngleStyle : int
{
///
/// 直角
///
Normal = 0,
///
/// 円角
///
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 m_TabRect = new List();
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; }
}
///
/// 表示タブの数
///
public int TabCount
{
get { return m_TabCount; }
set { m_TabCount = value; Invalidate(); }
}
private int m_ScrollButtonWidth = 35;
///
/// 浸り右
///
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 m_TabKeyList = new List();
//public List TabKeyList
//{
// get { return m_TabKeyList; }
// set { m_TabKeyList = value; }
//}
private List m_TabTextList = new List();
//public List 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 TabMark()
{
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
}
}