using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace AMT_SW_GUI { /// /// Each Form which like to include this TabControl need to register the OnParentPaintHandler of this class /// to its Paint event as follows: /// ParentControl.Paint += AMTTabControl_instance.OnParentPaintHandler; /// Purpose: /// This class is renderring itself instead of the system. /// Thus, when another window is hover this class control it should get an explicit redraw call from its container. /// public partial class AMTTabControl : TabControl { #region Private Memebers private PaintEventHandler m_OnParentPaintHandler; private Color m_SelectedTabBackgroundColor = Color.FromArgb(250, 249, 249); private Color m_UnSelectedTabBackgroundColor = Color.FromArgb(151, 182, 205); private Brush foregroundBrush; private Color foregroundColor = Color.Black; private Panel m_TopInternalBackground; private Panel m_RightInternalBackground; private Panel m_TopLeftInternalBackground; private Panel m_TopRightInternalBackground; private Panel m_LeftInternalBackground; private Image m_identifierImage; private int m_identifierWidth; private bool RTL; #endregion Private Memebers #region Public Methods private bool hasfocus; public AMTTabControl() { InitializeComponent(); Init(); TabSchema = this.schema; hasfocus = true; LostFocus += new EventHandler(AMTTabControl_LostFocus); RightToLeftChanged += new EventHandler(AMTTabControl_RightToLeftChanged); } public enum Schema { FamilyWhiteBg, Family, SCS, NONE } #endregion Public Methods #region Private Methods private void Init() { this.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; m_OnParentPaintHandler = new PaintEventHandler(OnParentPaint); Point temp = Padding; temp.X = temp.X + 3; Padding = temp; RTL = (RightToLeft == RightToLeft.Yes); if (RTL) m_identifierWidth = this.Location.X * 2 + this.ClientRectangle.Width - m_identifierWidth -1; } private void AMTTabControl_RightToLeftChanged(object sender, EventArgs e) { RTL = (RightToLeft == RightToLeft.Yes); if (RTL) m_identifierWidth = this.Location.X * 2 + this.ClientRectangle.Width - m_identifierWidth - 1; } private void OnParentPaint(object sender, PaintEventArgs e) { // this.Refresh(); } bool patched = false; private void PatchInternalBackground(DrawItemEventArgs e) { // add the internal background "patchy" panels if (null != m_RightInternalBackground && !patched) { m_RightInternalBackground.BackColor = panelColor;//area on right of all tabs m_RightInternalBackground.BackgroundImage = panelBackImage; } if (null != m_TopInternalBackground && !patched) { m_TopInternalBackground.BackColor = panelColor;//area on top of selected tab m_TopInternalBackground.BackgroundImage = m_identifierImage; } if (null != m_TopRightInternalBackground && !patched) { m_TopRightInternalBackground.BackColor = panelColor; //area on top of above area m_TopRightInternalBackground.BackgroundImage = panelBackImage; } if (null != m_TopLeftInternalBackground && !patched) { m_TopLeftInternalBackground.BackColor = panelColor;//top area to left of selected tab m_TopLeftInternalBackground.BackgroundImage = panelBackImage; } if (null != m_LeftInternalBackground && !patched) { m_LeftInternalBackground.BackColor = panelColor; m_LeftInternalBackground.BackgroundImage = panelBackImage; patched = true; } int x, y, w, h, padding; padding = 3; x = y = w = h = 0; // accumulate container offset in parent x = this.Location.X; y = this.Location.Y; // Fill the right side of the last tabPage with m_RightInternalBackground Panel if (e.Index == (this.TabCount - 1)) { if (this.SelectedIndex == e.Index) { x += (RTL) ? 0 : e.Bounds.X + e.Bounds.Width; y += this.ClientRectangle.Y + padding; w = this.ClientRectangle.Width - (e.Bounds.X + e.Bounds.Width); h = e.Bounds.Height - 2 * padding; m_RightInternalBackground.SetBounds(x, y, w, h); } else { x += (RTL) ? 0 : e.Bounds.X + e.Bounds.Width + padding; y += this.ClientRectangle.Y + padding; w = this.ClientRectangle.Width - (e.Bounds.X + e.Bounds.Width) - padding; h = e.Bounds.Height; m_RightInternalBackground.BringToFront(); m_RightInternalBackground.SetBounds(x, y, w, h); } } // Reset x, y x = this.Location.X; y = this.Location.Y; // Fill the top right side with m_TopRightInternalBackground Panel if (this.SelectedIndex == e.Index) { if (m_identifierWidth > 0 && m_identifierImage != null && SelectedIndex == 0) { x = (RTL) ? 0 : Math.Max(m_identifierWidth, x + e.Bounds.Width - 1); w = (RTL) ? m_identifierWidth : this.ClientRectangle.Width - x + 2 + this.Location.X; } else { x += (RTL) ? 0 : (e.Bounds.X + e.Bounds.Width - 2); w = this.ClientRectangle.Width - (e.Bounds.X + e.Bounds.Width) + 2; } y += this.ClientRectangle.Y; h = padding; m_TopRightInternalBackground.BringToFront(); m_TopRightInternalBackground.SetBounds(x, y, w, h); } // Reset x, y x = this.Location.X; y = this.Location.Y; // Fill the top of the selected tab with m_TopInternalBackground Panel if (m_identifierWidth > 0 && m_identifierImage != null) { // Reset x, y x = this.Location.X; y = this.Location.Y; if (this.SelectedIndex > 0) { if (this.SelectedIndex == e.Index) { m_TopInternalBackground.BringToFront(); x = (RTL) ? Math.Max(this.Width + this.Location.X - e.Bounds.X, m_identifierWidth) : x - 2; y += this.ClientRectangle.Y -1; w = (RTL) ? this.Location.X + this.Width - x : Math.Min(e.Bounds.X + padding, m_identifierWidth - x + 2); h = padding + 1; m_TopInternalBackground.SetBounds(x, y, w, h); m_TopInternalBackground.Margin = new Padding(0); } } else { if (this.SelectedIndex == e.Index) { // m_TopInternalBackground.SendToBack(); m_TopInternalBackground.BringToFront(); x = (RTL) ? m_identifierWidth : x + (e.Bounds.X + e.Bounds.Width - 2); y += this.ClientRectangle.Y -1; w = (RTL) ? this.Location.X + this.Width - x - e.Bounds.Width : m_identifierWidth - x + 2; h = padding + 1; m_TopInternalBackground.SetBounds(x, y, w, h); } } } // Reset x, y x = this.Location.X; y = this.Location.Y; // Fill the top left side with m_TopLeftInternalBackground Panel if (this.SelectedIndex == e.Index) { if (m_identifierWidth > 0 && m_identifierImage != null) { int temp = x; x += (RTL) ? this.Width - e.Bounds.X : Math.Min(e.Bounds.X + padding, m_identifierWidth - temp + 2); w = (RTL) ? m_identifierWidth - x : e.Bounds.X + padding - Math.Min(e.Bounds.X + padding, m_identifierWidth - temp + 2); } else { w = e.Bounds.X + padding - 3; if (RTL) x = this.Width + x - e.Bounds.X; } y += this.ClientRectangle.Y; h = padding; m_TopLeftInternalBackground.BringToFront(); m_TopLeftInternalBackground.SetBounds(x, y, w, h); } // Reset x, y x = (RTL) ? this.ClientRectangle.Width + this.Location.X - 3 : this.Location.X; y = this.Location.Y; // Fill the left side with m_LeftInternalBackground Panel if (this.SelectedIndex == 0) { y += this.ClientRectangle.Y + padding; w = padding; h = e.Bounds.Height - padding; m_LeftInternalBackground.BackColor = m_SelectedTabBackgroundColor; // if (m_LeftInternalBackground.BackgroundImage != null) { m_LeftInternalBackground.BringToFront(); m_LeftInternalBackground.BackgroundImage = null; m_LeftInternalBackground.SetBounds(x, y, w, h); } } else { if (e.Index != 0) { x += e.Bounds.X; } w = padding; y += this.ClientRectangle.Y; h = e.Bounds.Height + 4; if (m_LeftInternalBackground.BackgroundImage == null/* && m_identifierImage != null*/) { m_LeftInternalBackground.BringToFront(); m_LeftInternalBackground.BackgroundImage = (m_identifierImage != null) ? m_identifierImage : panelBackImage;//Properties.Resources.transparent_highlight; m_LeftInternalBackground.BackColor = Color.Transparent; m_LeftInternalBackground.SetBounds(x, y, w, h); } } } #endregion Private Methods #region Protected Methods protected override void OnDrawItem(DrawItemEventArgs e) { try { SuspendLayout(); Font font; Brush backgroundBrush; Brush backgroundBrushSelected; TabPageCollection tabPages = this.TabPages; if (e.Index == this.SelectedIndex) { font = new Font(e.Font, FontStyle.Regular); backgroundBrush = new SolidBrush(m_SelectedTabBackgroundColor); } else { font = e.Font; backgroundBrush = new SolidBrush(m_UnSelectedTabBackgroundColor); } backgroundBrushSelected = new SolidBrush(m_SelectedTabBackgroundColor); /// set the alignment of the caption string tabName = tabPages[e.Index].Text; StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; /// Draw border frame SelectedTab.BorderStyle = (schema == Schema.SCS) ? System.Windows.Forms.BorderStyle.FixedSingle : System.Windows.Forms.BorderStyle.None; Rectangle borderRect; int borderWidth = 4; /// left border Rectangle containerRect = this.ClientRectangle; borderRect = new Rectangle(containerRect.X, containerRect.Y + ItemSize.Height, borderWidth, containerRect.Height + 5); if (e.Index == 0 && e.Index == this.SelectedIndex) { borderRect.Y -= ItemSize.Height; borderRect.Height += ItemSize.Height; } e.Graphics.FillRectangle(backgroundBrush, borderRect); /// bottom border borderRect.X = containerRect.X; borderRect.Y = (containerRect.Y + containerRect.Height) - borderWidth; borderRect.Width = containerRect.Width; borderRect.Height = borderWidth; e.Graphics.FillRectangle(backgroundBrush, borderRect); /// right border borderRect.X = (containerRect.X + containerRect.Width) - borderWidth; borderRect.Y = containerRect.Y + ItemSize.Height; borderRect.Width = borderWidth; borderRect.Height = containerRect.Height; e.Graphics.FillRectangle(backgroundBrush, borderRect); /// top border borderRect.X = containerRect.X; borderRect.Y = containerRect.Y + ItemSize.Height; borderRect.Width = containerRect.Width; borderRect.Height = borderWidth; e.Graphics.FillRectangle(backgroundBrushSelected, borderRect); // drawing the tab itself Rectangle tabRect = (RTL) ? new Rectangle(containerRect.Width - e.Bounds.X - e.Bounds.Width, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height - 2) : new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height - 2); if (e.Index != this.SelectedIndex) { // set appropriate height for the unselected tabs tabRect.Height = tabRect.Height + 3; } //else // if (e.Index == 0) // { // tabRect.X += (RTL) ? 5 : -5; // tabRect.Width += (RTL) ? -5 : 5; // } e.Graphics.FillRectangle(backgroundBrush, tabRect); /* Prepare to string drawing */ Rectangle r = tabRect; int x = (RTL) ? this.Width - r.X - r.Width : r.X; r = new Rectangle(x, r.Y, r.Width, e.Bounds.Height); // e.Graphics.DrawString(tabName, font, foregroundBrush, r, sf); TextRenderer.DrawText(e.Graphics, tabName, font, r, foregroundColor); sf.Dispose(); if (e.Index == this.SelectedIndex) { font.Dispose(); } else { backgroundBrush.Dispose(); } backgroundBrushSelected.Dispose(); PatchInternalBackground(e); ResumeLayout(); } catch (Exception) { // should log to debug log something here } } protected override void OnGotFocus(EventArgs e) { if (!hasfocus) { this.Refresh(); } hasfocus = true; base.OnGotFocus(e); } public void gotFocus() { OnGotFocus(null); } void AMTTabControl_LostFocus(object sender, EventArgs e) { hasfocus = false; this.Refresh(); } protected override void OnMouseLeave(EventArgs e) { // base.OnMouseLeave(e); // this.Refresh(); } protected override void OnMouseHover(EventArgs e) { // base.OnMouseHover(e); // this.Refresh(); } protected override void OnMouseEnter(EventArgs e) { //base.OnMouseEnter(e); } protected override void OnMouseMove(MouseEventArgs e) { //base.OnMouseMove(e); } protected override void OnEnter(EventArgs e) { //base.OnEnter(e); } #endregion Protected Methods #region Properties /// /// An Handler to be registerred on parent control Paint event: /// ParentControl.Paint += AMTTabControl_instance.OnParentPaintHandler; /// public PaintEventHandler OnParentPaintHandler { get { return m_OnParentPaintHandler; } } public Color SelectedTabBackgroundColor { get { return m_SelectedTabBackgroundColor; } set { if (TabSchema == Schema.NONE) m_SelectedTabBackgroundColor = value; } } public Color TabTextColor { get { return foregroundColor; } set { if (TabSchema == Schema.NONE) { foregroundColor = value; ; foregroundBrush = new SolidBrush(foregroundColor); } } } public Image IdentifierImage { get { return m_identifierImage; } set { if (TabSchema == Schema.NONE || TabSchema == Schema.Family || TabSchema == Schema.FamilyWhiteBg) { m_identifierImage = value; } } } public int IdentifierWidth { get { return m_identifierWidth; } set { m_identifierWidth = value; } } public Color UnSelectedTabBackgroundColor { get { return m_UnSelectedTabBackgroundColor; } set { if (TabSchema == Schema.NONE) m_UnSelectedTabBackgroundColor = value; } } public Panel RightInternalBackground { get { return m_RightInternalBackground; } set { m_RightInternalBackground = value; } } public Panel TopInternalBackground { get { return m_TopInternalBackground; } set { m_TopInternalBackground = value; } } public Panel TopLeftInternalBackground { get { return m_TopLeftInternalBackground; } set { m_TopLeftInternalBackground = value; } } public Panel TopRightInternalBackground { get { return m_TopRightInternalBackground; } set { m_TopRightInternalBackground = value; } } public Panel LeftInternalBackground { get { return m_LeftInternalBackground; } set { m_LeftInternalBackground = value; } } private Color panelColor = Color.Transparent; private Image panelBackImage = Properties.Resources.transparent_highlight; private Schema schema; public Schema TabSchema { get { return schema; } set { schema = value; switch (schema) { case Schema.Family: { m_SelectedTabBackgroundColor = Color.FromArgb(250, 249, 249); m_UnSelectedTabBackgroundColor = Color.FromArgb(151, 182, 205); panelColor = Color.Transparent; panelBackImage = Properties.Resources.transparent_highlight; foregroundBrush = Brushes.Black; return; } case Schema.SCS : { m_SelectedTabBackgroundColor = Color.FromArgb(86, 126, 185); m_UnSelectedTabBackgroundColor = Color.FromArgb(151, 182, 205); panelColor = Color.White; panelBackImage = Properties.Resources.inner_pane_center; foregroundBrush = new SolidBrush(Color.White); return; } case Schema.FamilyWhiteBg: { m_SelectedTabBackgroundColor = Color.FromArgb(86, 126, 185); m_UnSelectedTabBackgroundColor = Color.FromArgb(151, 182, 205); panelColor = Color.White; panelBackImage = Properties.Resources.inner_pane_center; foregroundBrush = new SolidBrush(Color.White); return; } case Schema.NONE: { return; } } } } #endregion Properties } }