Ejemplo n.º 1
0
        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.Clear(Color.White);
            foreach (TabPage tabPage in TabPages)
            {
                int       curIndex = TabPages.IndexOf(tabPage);
                Rectangle tabRect  = GetTabRect(curIndex);
                var       titleR   = new Rectangle(tabRect.X, tabRect.Y, tabRect.Width, tabRect.Height);
                var       ntr      = new Rectangle(tabRect.X + (curIndex == 0 ? 2 : 0), (tabRect.Y + tabRect.Height) - 3, tabRect.Width - (curIndex == 0 ? 4 : 2), 2);

                if (Alignment == TabAlignment.Top)
                {
                    e.Graphics.FillRectangle(SelectedIndex == curIndex ? Color.FromArgb(243, 63, 63) : Color.Silver, ntr);
                    e.Graphics.DrawString(tabPage.Text, Font, Color.Black, titleR, StringAlignment.Center);
                }
                else if (Alignment == TabAlignment.Right)
                {
                    titleR = new Rectangle(titleR.X + 4, titleR.Y, titleR.Width, titleR.Height);
                    ntr    = new Rectangle(tabRect.X, tabRect.Y + (curIndex == 0 ? 2 : 0), 2, tabRect.Height - (curIndex == 0 ? 4 : 2));
                    e.Graphics.FillRectangle(SelectedIndex == curIndex ? Color.FromArgb(243, 63, 63) : Color.Silver, ntr);
                    e.Graphics.DrawString(tabPage.Text, Font, Color.Black, titleR, StringAlignment.Near, StringAlignment.Center);
                }
            }

            if (_displayBoundary)
            {
                e.Graphics.DrawLine(Color.FromArgb(243, 63, 63), 0, Height - 1, Width - 1, Height - 1);
            }
            base.OnPaint(e);
        }
        /// <summary>
        /// Removes a tab
        /// </summary>
        /// <param name="Target">The tab that will be removed</param>
        public void ProfileTabRemove(TabPage Target)
        {
            if (ReadOnlyMode)
            {
                System.Media.SystemSounds.Beep.Play();
                return; // control not editable
            }

            // Remove tab but we still need to keep last regular one, the "New" and "Delete tabs.
            if (TabPages.Count <= 3)
            {
                return;
            }

            // Mono workaround: Selection required otherwise empty tab will be shown after deletion
            // Solution: Select last available tab (as it gets shifted due to deletion
            //           This way we force TabControl to re-select tab upon deletion
            SelectedIndex = TabPages.Count - 3;

            int index = TabPages.IndexOf(Target);

            ProfileTabSelectedHandler((ProfileViewControl)Target.Controls["pvc"], ProfileTabSelectAction.Deleting);
            TabPages.RemoveAt(index);

            for (int i = TabPages.Count - 3; 0 <= i; i--)
            {
                TabPages[i].Text = (i + 1).ToString(); // Update tab names
            }

            // Mono workaround: Selection required otherwise empty tab will be shown after deletion
            // Solution: Due to new selection the tab will be loaded properly again and no empty page is shown
            SelectedIndex = (index == 0 ? 0 : index - 1);
        }
Ejemplo n.º 3
0
        private void ChangeTab(LcarsTabPage tab)
        {
            //Brings the provided tab to the front of all of the other tabs and sets it as
            //the selected tab.

            //NOTE: tab is used because if we used the property to set the selected tab,
            //we would get into an 'endless loop' because the 'SelectedTab' property calls
            //'ChangeTab' which in turn would call 'SelectedTab' again.  Not good!
            if (tab != null)
            {
                tab.BringToFront();
                selectedTab = tab;

                //Set the heading(the bar at the top)'s text to the tab's text
                horizantalBar.Text = tab.Text;

                //Set the selected tabs button's red alert to white and all others to normal
                foreach (FlatButton mybutton in tabButtonPanel.Controls)
                {
                    if (ReferenceEquals(mybutton.Tag, tab))
                    {
                        mybutton.AlertState = LcarsAlert.White;
                    }
                    else
                    {
                        mybutton.AlertState = LcarsAlert.Normal;
                    }
                }
            }

            //Let the user of the control know that a tab has been selected.
            SelectedTabChanged?.Invoke(tab, TabPages.IndexOf(tab));
        }
Ejemplo n.º 4
0
        protected override void OnDragOver(DragEventArgs e)
        {
            base.OnDragOver(e);

            TabPage hoverTab = HoverTab();

            if (hoverTab == null)
            {
                e.Effect = DragDropEffects.None;
            }
            else
            {
                if (e.Data.GetDataPresent(typeof(DwarfTabPage)))
                {
                    e.Effect = DragDropEffects.Move;
                    TabPage dragTab = (TabPage)e.Data.GetData(typeof(DwarfTabPage));

                    if (hoverTab == dragTab)
                    {
                        return;
                    }

                    Rectangle tabRect = GetTabRect(TabPages.IndexOf(hoverTab));
                    tabRect.Inflate(-3, -3);
                    if (tabRect.Contains(PointToClient(new Point(e.X, e.Y))))
                    {
                        SwapTabPages(dragTab, hoverTab);
                        SelectedTab = dragTab;
                    }
                }
            }
        }
Ejemplo n.º 5
0
        void _MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
            {
                // Find out which tab has been clicked & close that file.
                //
                for (int i = 0; i < TabCount; i++)
                {
                    if (GetTabRect(i).Contains(e.X, e.Y))
                    {
                        CloseFile((FileEditorTab)TabPages[i]);
                    }
                }
            }

            if (e.Button == MouseButtons.Left)
            {
                // Left click already sets the target tab to selected so no need to do the stuff we do for the middle mouse button (looping through all the tabs)
                //
                int       tabIndex = TabPages.IndexOf(SelectedTab);
                Rectangle r        = ConvertRectangleBounds_CloseButton(GetTabRect(tabIndex));

                if (r.Contains(e.Location))
                {
                    CloseFile(this.SelectedFileTab);
                    SelectedIndex = tabIndex;
                }
            }
        }
Ejemplo n.º 6
0
        public void AddTab(string filename = "")
        {
            if (TabPages.ContainsKey(filename))
            {
                return;
            }

            var tabPage = new TabPage();

            if (string.IsNullOrEmpty(filename))
            {
                tabPage.Text       = Strings.DocumentsTabControl_AddTab_NewFile + id;
                tabPage.ImageIndex = 1;
                tabPage.Name       = Strings.DocumentsTabControl_AddTab_NewFile + id;
            }
            else
            {
                tabPage.Text       = filename;
                tabPage.ImageIndex = 0;
                tabPage.Name       = filename;
            }
            TabPages.Insert(TabPages.Count - 1, tabPage);
            SelectedIndex = TabPages.IndexOf(tabPage);
            id++;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 绘制
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            using (SolidBrush sb = new SolidBrush(Color.FromArgb(37, 37, 37)))
            {
                Rectangle all_back = new Rectangle(1, 1, Width - 2, Height - 2);  //整个背景区域
                e.Graphics.FillRectangle(sb, all_back);

                Rectangle back = new Rectangle(ItemSize.Width + 1, 1, Width - ItemSize.Width - 2, Height - 2);  //客户区
                e.Graphics.FillRectangle(Brushes.White, back);
                e.Graphics.DrawRectangle(Pens.Gray, back);

                foreach (TabPage tab in TabPages)  //Tab
                {
                    Rectangle tab_rect = GetTabRect(TabPages.IndexOf(tab));
                    tab_rect = new Rectangle(tab_rect.X - 1, tab_rect.Y - 1, tab_rect.Width, tab_rect.Height);
                    if (this.SelectedTab == tab || TabPages.IndexOf(tab) == _mouse_over)
                    {
                        using (SolidBrush bsb = new SolidBrush(Color.FromArgb(51, 133, 255)))
                        {
                            e.Graphics.FillRectangle(bsb, tab_rect);
                        }
                        e.Graphics.DrawString(tab.Text, new Font("微软雅黑", 10), Brushes.White, new PointF(tab_rect.X + 18, tab_rect.Y + 20));
                    }
                    else
                    {
                        e.Graphics.FillRectangle(sb, tab_rect);
                        e.Graphics.DrawString(tab.Text, new Font("微软雅黑", 10), Brushes.White, new PointF(tab_rect.X + 18, tab_rect.Y + 20));
                    }
                }
            }
        }
        private void SwapTabPages(TabPage src, TabPage dst)
        {
            int srcIndex = TabPages.IndexOf(src);
            int dstIndex = TabPages.IndexOf(dst);

            if (PlatformHelper.GetPlatform() == Platform.Linux || PlatformHelper.GetPlatform() == Platform.OsX)
            {
                TabPages.Insert(dstIndex, src);
                TabPages.Insert(srcIndex, dst);
            }
            else
            {
                TabPages[dstIndex] = src;
                TabPages[srcIndex] = dst;
            }

            if (SelectedIndex == srcIndex)
            {
                SelectedIndex = dstIndex;
            }
            else if (SelectedIndex == dstIndex)
            {
                SelectedIndex = srcIndex;
            }

            Refresh();
        }
Ejemplo n.º 9
0
        public void CloseTab(TabPage tp, bool askConfirmation = false)
        {
            int index = TabPages.IndexOf(tp);

            if (index < 0)
            {
                return;
            }

            if (!askConfirmation ||
                !Program.Model.Settings.ShowCloseTabConfirmation ||
                MessageBox.Show(
                    Program.Model.LocaleManager.GetLocalizedText(GetType().Name, "shouldClose"),
                    Program.Model.LocaleManager.GetLocalizedText(GetType().Name, "tabClose"),
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question
                    ) == DialogResult.Yes
                )
            {
                TabPages.Remove(tp);

                SelectedIndex = index != 0 ? index - 1 : 0;

                this._btnCloseList.Clear();
                this._recreate = true;
            }
        }
Ejemplo n.º 10
0
        public void Repos(TabPage tpCurrent)
        {
            Button btnClose = CloseButton(tpCurrent);

            if (btnClose != null)
            {
                int tpIndex = TabPages.IndexOf(tpCurrent);
                if (tpIndex >= 0)
                {
                    Rectangle rctCurrent = GetTabRect(tpIndex);

                    if (SelectedTab == tpCurrent)
                    {
                        btnClose.Size     = new Size(rctCurrent.Height - 1, rctCurrent.Height - 1);
                        btnClose.Location = new Point(rctCurrent.X + rctCurrent.Width - rctCurrent.Height, rctCurrent.Y + 1);
                    }
                    else
                    {
                        btnClose.Size     = new Size(rctCurrent.Height - 3, rctCurrent.Height - 2);
                        btnClose.Location = new Point(rctCurrent.X + rctCurrent.Width - rctCurrent.Height - 1, rctCurrent.Y + 1);
                    }

                    btnClose.Visible = ShowCloseButtons;
                    btnClose.BringToFront();
                }
            }
        }
Ejemplo n.º 11
0
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (m.Msg == (int)User32.Msgs.WM_NCHITTEST)
            {
                if (m.Result.ToInt32() == User32._HT_TRANSPARENT)
                {
                    m.Result = (IntPtr)User32._HT_CLIENT;
                }
            }

            if (m.Msg == (int)User32.Msgs.WM_LBUTTONDOWN)
            {
                if (this.TabCount > 1)
                {
                    TabPage selectingTabPage = OverTab();
                    if (selectingTabPage != null)
                    {
                        int index = TabPages.IndexOf(selectingTabPage);
                        if (index != this.SelectedIndex)
                        {
                            if (!selectingTabPage.Enabled)
                            {
                                m.Result = new IntPtr(1);
                            }
                            else
                            {
                                this.SelectedTab = selectingTabPage;
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 12
0
        public bool IsOverCloseButton(Point p)
        {
            Rectangle r = GetTabRect(TabPages.IndexOf(TabPageFromPoint(p)));
            int       x = p.X - r.X, y = p.Y - r.Y;

            return(x > 4 && x < 24 && y > 1 && y < 17);
        }
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(e);

            if (SelectedTab == TabPages[e.Index])
            {
                e.Graphics.FillRectangle(new SolidBrush(Color.Tomato), e.Bounds);
                Rectangle rtCurrent =
                    GetTabRect(TabPages.IndexOf(SelectedTab));
                buttonX.Location = new Point(
                    rtCurrent.X + rtCurrent.Width - buttonX.Width,
                    rtCurrent.Y
                    );
            }
            else
            {
                e.Graphics.FillRectangle(new SolidBrush(Color.Tan), e.Bounds);
            }

            TabPages[e.Index].BorderStyle = BorderStyle.FixedSingle;
            TabPages[e.Index].ForeColor   = SystemColors.ControlText;

            Rectangle paddedBounds = e.Bounds;

            paddedBounds.Inflate(-2, -3);

            e.Graphics.DrawString(
                TabPages[e.Index].Text,
                Font,
                SystemBrushes.HighlightText,
                paddedBounds);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Handles the event that occurs when an object is dragged over the control's bounds.
        /// </summary>
        /// <param name="drgevent"></param>
        protected override void OnDragOver(DragEventArgs drgevent)
        {
            // Check whether there is no tab being dragged
            if (drgevent.Data.GetData(typeof(TabPage)) == null)
            {
                return;
            }

            // Get drag tab and its index
            TabPage dragTab      = (TabPage)drgevent.Data.GetData(typeof(TabPage));
            int     dragTabIndex = TabPages.IndexOf(dragTab);

            // Check whether a tab is being dragged
            if (dragTabIndex < 0)
            {
                return;
            }

            // Check whether the mouse if over a tab
            int hoverTabIndex = GetHoverTabIndex();

            if (hoverTabIndex < 0)
            {
                drgevent.Effect = DragDropEffects.None;
                return;
            }
            TabPage hoverTab = TabPages[hoverTabIndex];

            drgevent.Effect = DragDropEffects.Move;

            // Check whether this is the start of the drag
            if (dragTab == hoverTab)
            {
                return;
            }

            // Swap tabs
            Rectangle dragTabRect  = GetTabRect(dragTabIndex);
            Rectangle hoverTabRect = GetTabRect(hoverTabIndex);

            if (dragTabRect.Width < hoverTabRect.Width)
            {
                if (dragTabIndex < hoverTabIndex && ((drgevent.X - Location.X) > ((hoverTabRect.X + hoverTabRect.Width) - dragTabRect.Width)))
                {
                    SwapTabPages(dragTab, hoverTab); // Swap tab locations
                }
                else if (dragTabIndex > hoverTabIndex && ((drgevent.X - Location.X) < (hoverTabRect.X + dragTabRect.Width)))
                {
                    SwapTabPages(dragTab, hoverTab); // Swap tab locations
                }
            }
            else
            {
                SwapTabPages(dragTab, hoverTab); // Swap tab locations
            }

            // Select the dragged tab
            SelectedIndex = TabPages.IndexOf(dragTab);
        }
Ejemplo n.º 15
0
        private void SwapTabPages(TabPage tp1, TabPage tp2)
        {
            int index1 = TabPages.IndexOf(tp1);
            int index2 = TabPages.IndexOf(tp2);

            TabPages[index1] = tp2;
            TabPages[index2] = tp1;
        }
Ejemplo n.º 16
0
        private bool IsCloseButtonClick(MetroTabPage page, Point location)
        {
            var index         = TabPages.IndexOf(page);
            var rectangle     = GetTabRect(index);
            var closeRectagle = GetCloseButtonRectangle(rectangle);

            return(IsInCloseButtonArea(closeRectagle, location));
        }
        private void Swap(TabPage a, TabPage b)
        {
            int i = TabPages.IndexOf(a);
            int j = TabPages.IndexOf(b);

            TabPages[i] = b;
            TabPages[j] = a;
        }
Ejemplo n.º 18
0
        private void buttonAction(cnTabButton sender, TabButtonAction action)
        {
            if ((action == TabButtonAction.Left) || (action == TabButtonAction.Up))
            {
                offsetX -= tabWidth;
                if (offsetX < 0)
                {
                    offsetX = 0;
                }
            }
            else if ((action == TabButtonAction.Right) || (action == TabButtonAction.Down))
            {
                int l = tabWidth;
                if (tabView == TabControlView.OneNote)
                {
                    l += tabHeight / 2 + 3;
                }
                offsetX += l;
                int       full_l = l * TabPages.Count;
                Rectangle r      = this.GetBoundsHeader(0);
                Rectangle rb     = this.GetBoundsButtons();
                int       d;
                if ((Alignment == TabAlignment.Top) || (Alignment == TabAlignment.Bottom))
                {
                    d = r.Width - rb.Width;
                }
                else
                {
                    d = r.Height - rb.Height;
                }

                if (full_l < d)
                {
                    offsetX = 0;
                }
                else
                if (d + offsetX > full_l)
                {
                    offsetX = full_l - d;
                }
            }
            else if (action == TabButtonAction.Action)
            {
                ContextMenuStrip menu = new ContextMenuStrip();
                foreach (cnTabPage tb in TabPages)
                {
                    ToolStripMenuItem item = new System.Windows.Forms.ToolStripMenuItem();
                    item.Text = tb.Title;
                    int n = TabPages.IndexOf(tb);
                    item.Tag     = n;
                    item.Checked = (n == currentPage);
                    item.Click  += new System.EventHandler(ItemClickMenu);
                    menu.Items.Add(item);
                }
                menu.Show(sender, 0, sender.Size.Height);
            }
            Invalidate();
        }
Ejemplo n.º 19
0
        /// <summary>
        /// On drag and drop, we updates the tab order.
        /// </summary>
        /// <param name="drgevent"></param>
        protected override void OnDragDrop(DragEventArgs drgevent)
        {
            TabPage draggedTab = GetDraggedTab(drgevent);

            m_lastPoint   = new Point(Int32.MaxValue, Int32.MaxValue);
            m_markerIndex = -1;
            UpdateMarker();

            // Retrieve the point in client coordinates
            Point pt = new Point(drgevent.X, drgevent.Y);

            pt = PointToClient(pt);

            // Get the tab we are hovering over.
            bool onLeft;
            int  markerIndex = GetMarkerIndex(draggedTab, pt, out onLeft);
            int  index       = GetInsertionIndex(markerIndex, onLeft);

            // Make sure there is a TabPage being dragged.
            if (draggedTab == null)
            {
                drgevent.Effect = DragDropEffects.None;
                base.OnDragDrop(drgevent);
                return;
            }

            // Retrieve the dragged page. If same as dragged page, return
            int draggedIndex = TabPages.IndexOf(draggedTab);

            if (draggedIndex == index || (draggedIndex == index - 1 && onLeft))
            {
                drgevent.Effect = DragDropEffects.None;
                base.OnDragDrop(drgevent);
                return;
            }

            // Move the tabs
            drgevent.Effect = DragDropEffects.Move;
            this.SuspendDrawing();
            SuspendLayout();
            try
            {
                if (TabPages.IndexOf(draggedTab) < index)
                {
                    index--;
                }
                TabPages.Remove(draggedTab);
                TabPages.Insert(index, draggedTab);
                SelectedTab = draggedTab;
            }
            finally
            {
                ResumeLayout(false);
                this.ResumeDrawing();
                base.OnDragDrop(drgevent);
            }
        }
 public void HidePage(TabPage tabPage)
 {
     if (TabPages.Contains(tabPage))
     {
         int v = TabPages.IndexOf(tabPage);
         HiddenPages.Add(tabPage);
         lastIndex.Add(v);
         TabPages.RemoveAt(v);
     }
 }
Ejemplo n.º 21
0
        public void SelectTab(TabPage tabPage)
        {
            var index = TabPages.IndexOf(tabPage);

            if (index == -1)
            {
                return;
            }
            SelectTab(index);
        }
Ejemplo n.º 22
0
        private void HandleTabRightClickClose(object sender, EventArgs e)
        {
            var control = sender as PluginTab;

            var index = TabPages.IndexOf(control);

            if (index > -1)
            {
                CloseTab(index);
            }
        }
Ejemplo n.º 23
0
        private TabPage TabAt(System.Drawing.Point position)
        {
            foreach (TabPage tab in this.TabPages)
            {
                if (this.GetTabRect(TabPages.IndexOf(tab)).Contains(position))
                {
                    return(tab);
                }
            }

            return(null);
        }
        public void SwapTabPages(TabPage tp1, TabPage tp2)
        {
            if (!TabPages.Contains(tp1) || !TabPages.Contains(tp2))
            {
                throw new ArgumentException("TabPages must be in the TabCotrols TabPageCollection.");
            }
            int Index1 = TabPages.IndexOf(tp1);
            int Index2 = TabPages.IndexOf(tp2);

            TabPages[Index1] = tp2;
            TabPages[Index2] = tp1;
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Swaps the location of two provided TabPages.
        /// </summary>
        /// <param name="srcTab">TabPage 1</param>
        /// <param name="dstTab">TabPage 2</param>
        private void SwapTabPages(TabPage srcTab, TabPage dstTab)
        {
            // Swap tab indexes
            int srcIndex = TabPages.IndexOf(srcTab);
            int dstIndex = TabPages.IndexOf(dstTab);

            TabPages[dstIndex] = srcTab;
            TabPages[srcIndex] = dstTab;

            TabSwapped?.Invoke(this, new TabSwapEventArgs(srcIndex, dstIndex));
            Refresh();
        }
Ejemplo n.º 26
0
        /// <summary>Swaps the tab pages.</summary>
        /// <param name="tabPage1">The tab page.</param>
        /// <param name="tabPage2">The other tab page.</param>
        public void SwapTabPages(TabPage tabPage1, TabPage tabPage2)
        {
            if (!TabPages.Contains(tabPage1) || !TabPages.Contains(tabPage2))
            {
                throw new ArgumentException(@"TabPages must be in the TabControls TabPageCollection.");
            }

            int _index1 = TabPages.IndexOf(tabPage1);
            int _index2 = TabPages.IndexOf(tabPage2);

            TabPages[_index1] = tabPage2;
            TabPages[_index2] = tabPage1;
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Handles the event that occurs when the mouse pointer is moved over the control.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if ((e.Button != MouseButtons.Left) || (Tag == null))
            {
                return;
            }

            // Get clicked tab
            TabPage clickedTab   = (TabPage)Tag;
            int     clickedIndex = TabPages.IndexOf(clickedTab);

            // Start drag and drop
            DoDragDrop(clickedTab, DragDropEffects.All);
        }
Ejemplo n.º 28
0
 /// <summary>
 /// 鼠标进入选项卡
 /// </summary>
 /// <param name="e"></param>
 protected override void OnMouseMove(MouseEventArgs e)
 {
     base.OnMouseMove(e);
     _mouse_over = -1;
     foreach (TabPage tab in TabPages)
     {
         Rectangle tab_tect = GetTabRect(TabPages.IndexOf(tab));
         if (tab_tect.Contains(e.Location))
         {
             _mouse_over = TabPages.IndexOf(tab);
             break;
         }
     }
 }
Ejemplo n.º 29
0
        public void CloseTab(TabPage tp)
        {
            ClosingEventArgs args = new ClosingEventArgs(TabPages.IndexOf(tp));

            OnTabClosing(args);
            //Remove the tab and fir the event tot he client
            if (!args.Cancel)
            {
                // close and remove the tab, dispose it too
                TabPages.Remove(tp);
                OnTabClosed(new ClosedEventArgs(tp));
                tp.Dispose();
            }
        }
Ejemplo n.º 30
0
        // http://stackoverflow.com/questions/1849801/c-sharp-winform-how-to-set-the-base-color-of-a-tabcontrol-not-the-tabpage
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            // fill in the whole rect
            using (SolidBrush br = new SolidBrush(Color.Black))
            {
                e.Graphics.FillRectangle(br, ClientRectangle);
            }

            // draw the tabs
            for (int i = 0; i < TabPages.Count; ++i)
            {
                TabPage tab = TabPages[i];
                // Get the text area of the current tab
                RectangleF tabTextArea = (RectangleF)GetTabRect(i);
                tabTextArea.Width  *= e.Graphics.DpiX / 96f;
                tabTextArea.Height *= e.Graphics.DpiY / 96f;

                // draw the background
                var tabColor = SelectedTab == tab ? SelectedTabBackColor : TabBackColor;
                using (SolidBrush br = new SolidBrush(tabColor))
                {
                    e.Graphics.FillRectangle(br, tabTextArea);
                }

                // draw the border
                using (Pen p = new Pen(TabBorderColor))
                {
                    e.Graphics.DrawRectangle(p, tabTextArea.X, tabTextArea.Y, tabTextArea.Width, tabTextArea.Height);
                }

                // draw the tab header text
                var textColor = SelectedTab == tab ? SelectedTabForeColor : TabForeColor;
                using (SolidBrush brush = new SolidBrush(textColor))
                {
                    var sf = new StringFormat();
                    sf.Alignment     = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    e.Graphics.DrawString(tab.Text, Font, brush, tabTextArea, sf);
                }
            }

            // draw the tab underline (same color as border)
            var bottom = TabPages.Cast <TabPage>().MaxOrDefault(t => GetTabRect(TabPages.IndexOf(t)).Bottom);

            using (Pen p = new Pen(TabBorderColor, 5))
            {
                e.Graphics.DrawLine(p, ClientRectangle.Left, bottom, ClientRectangle.Right, bottom);
            }
        }