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 } }