#region Imports using DPumpHydr.WinFrmUI.RLT.Animate.Metro; using DPumpHydr.WinFrmUI.RLT.Child.Metro; using DPumpHydr.WinFrmUI.RLT.Design.Metro; using DPumpHydr.WinFrmUI.RLT.Enum.Metro; using DPumpHydr.WinFrmUI.RLT.Extension.Metro; using DPumpHydr.WinFrmUI.RLT.Interface.Metro; using DPumpHydr.WinFrmUI.RLT.Manager; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Runtime.InteropServices; using System.Windows.Forms; #endregion namespace DPumpHydr.WinFrmUI.RLT.Controls { #region MetroTabControl [ToolboxItem(true)] [ToolboxBitmap(typeof(MetroTabControl), "Bitmaps.TabControl.bmp")] #if NET48_OR_GREATER [Designer(typeof(MetroTabControlDesigner))] #endif [ComVisible(true)] public class MetroTabControl : TabControl, IMetroControl { #region Interfaces [Category("Metro"), Description("Gets or sets the style associated with the control.")] public Style Style { get => StyleManager?.Style ?? _style; set { _style = value; switch (value) { case Style.Light: ApplyTheme(); break; case Style.Dark: ApplyTheme(Style.Dark); break; case Style.Custom: ApplyTheme(Style.Custom); break; default: ApplyTheme(); break; } Invalidate(); } } [Category("Metro"), Description("Gets or sets the Style Manager associated with the control.")] public MetroStyleManager StyleManager { get => _styleManager; set { _styleManager = value; Invalidate(); } } [Category("Metro"), Description("Gets or sets the The Author name associated with the theme.")] public string ThemeAuthor { get; set; } [Category("Metro"), Description("Gets or sets the The Theme name associated with the theme.")] public string ThemeName { get; set; } #endregion Interfaces #region Global Vars private readonly Methods _mth; private readonly Utilites _utl; #endregion Global Vars #region Internal Vars private Style _style; private MetroStyleManager _styleManager; private readonly PointFAnimate _slideAnimator; private Graphics _slideGraphics; private Bitmap _slideBitmap; private bool _isDerivedStyle = true; private bool _useAnimation = true; private int _speed = 100; private Color _unselectedTextColor; private Color _selectedTextColor; private TabStyle _tabStyle; #endregion Internal Vars #region Constructors public MetroTabControl() { SetStyle ( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true ); UpdateStyles(); ItemSize = new(100, 38); Font = MetroFonts.UIRegular(8); _mth = new Methods(); _utl = new Utilites(); _slideAnimator = new PointFAnimate(); if (Cursor == null) { Cursor = MCursor; } MCursor = Cursor; ApplyTheme(); } #endregion Constructors #region ApplyTheme private void ApplyTheme(Style style = Style.Light) { if (!IsDerivedStyle) { return; } switch (style) { case Style.Light: ForegroundColor = Color.FromArgb(65, 177, 225); BackgroundColor = Color.White; UnselectedTextColor = Color.Gray; if (TabStyle == TabStyle.Style1) { SelectedTextColor = Color.White; } else { SelectedTextColor = ForegroundColor; } ThemeAuthor = "Taiizor"; ThemeName = "MetroLight"; UpdateProperties(); break; case Style.Dark: ForegroundColor = Color.FromArgb(65, 177, 225); BackgroundColor = Color.FromArgb(30, 30, 30); UnselectedTextColor = Color.Gray; if (TabStyle == TabStyle.Style1) { SelectedTextColor = Color.White; } else { SelectedTextColor = ForegroundColor; } ThemeAuthor = "Taiizor"; ThemeName = "MetroDark"; UpdateProperties(); break; case Style.Custom: if (StyleManager != null) { foreach (System.Collections.Generic.KeyValuePair varkey in StyleManager.TabControlDictionary) { switch (varkey.Key) { case "ForeColor": ForegroundColor = _utl.HexColor((string)varkey.Value); break; case "BackColor": BackgroundColor = _utl.HexColor((string)varkey.Value); break; case "UnselectedTextColor": UnselectedTextColor = _utl.HexColor((string)varkey.Value); break; case "SelectedTextColor": SelectedTextColor = _utl.HexColor((string)varkey.Value); break; default: return; } } } UpdateProperties(); break; } } private void UpdateProperties() { try { InvalidateTabPage(BackgroundColor); Invalidate(); Refresh(); } catch { //throw new Exception(Ex.StackTrace); } } #endregion ApplyTheme #region Properties [Category("Metro"), Description("Get or set slide animate time(ms).")] public int AnimateTime { get; set; } = 200; [Category("Metro"), Description("Get or set slide animate easing type")] public EasingType AnimateEasingType { get; set; } = EasingType.CubeOut; [Category("Metro")] [Editor(typeof(MetroTabPageCollectionEditor), typeof(UITypeEditor))] public new TabPageCollection TabPages => base.TabPages; [Category("Metro"), Description("Gets or sets wether the tabcontrol use animation or not.")] [DefaultValue(true)] public bool UseAnimation { get => _useAnimation; set { _useAnimation = value; Refresh(); } } [Category("Metro"), Description("Gets or sets the size of the control's tabs.")] public new Size ItemSize { get => base.ItemSize; set { base.ItemSize = value; Invalidate(); } } [Category("Metro"), Description("Gets or sets the font used when displaying text in the control.")] public new Font Font { get; set; } [Category("Metro"), Description("Gets or sets the area of the control (for example, along the top) where the tabs are aligned.")] public new TabAlignment Alignment => TabAlignment.Top; [Category("Metro"), Description("Gets or sets the speed of transition.")] [DefaultValue(20)] public int Speed { get => _speed; set { _speed = value; Refresh(); } } [Category("Metro")] public override DockStyle Dock { get => base.Dock; set => base.Dock = value; } [Category("Metro"), Description("Gets or sets the visible of page controls.")] public bool ControlsVisible { get; set; } = true; [Category("Metro"), Description("Gets or sets the cursor of control.")] public Cursor MCursor { get; set; } = Cursors.Hand; [Browsable(false)] public Cursor Cursor { get; set; } [Category("Metro")] [Browsable(false)] public new TabSizeMode SizeMode { get; set; } = TabSizeMode.Fixed; [Category("Metro")] [Browsable(false)] public new TabDrawMode DrawMode { get; set; } = TabDrawMode.Normal; [Category("Metro"), Description("Gets or sets the backgorund color.")] public Color BackgroundColor { get; set; } [Category("Metro"), Description("Gets or sets the foregorund color.")] private Color ForegroundColor { get; set; } [Category("Metro"), Description("Gets or sets the tabpage text while un-selected.")] public Color UnselectedTextColor { get => _unselectedTextColor; set { _unselectedTextColor = value; Refresh(); } } [Category("Metro"), Description("Gets or sets the tabpage text while selected.")] public Color SelectedTextColor { get => _selectedTextColor; set { _selectedTextColor = value; Refresh(); } } [Category("Metro"), Description("Gets or sets the tancontrol apperance style.")] [DefaultValue(TabStyle.Style1)] public TabStyle TabStyle { get => _tabStyle; set { _tabStyle = value; if (_tabStyle == TabStyle.Style1) { SelectedTextColor = Color.White; } else if (_tabStyle == TabStyle.Style2) { SelectedTextColor = ForegroundColor; } Refresh(); } } [Category("Metro")] [Description("Gets or sets the whether this control reflect to parent(s) style. \n " + "Set it to false if you want the style of this control be independent. ")] public bool IsDerivedStyle { get => _isDerivedStyle; set { _isDerivedStyle = value; Refresh(); } } #endregion Properties #region Draw Control protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; g.Clear(BackgroundColor); int h = ItemSize.Height + 2; switch (TabStyle) { case TabStyle.Style1: using (Pen sb = new(ForegroundColor, 2)) { g.DrawLine(sb, 2, h, Width - 3, h); } for (int i = 0; i <= TabCount - 1; i++) { Rectangle r = GetTabRect(i); if (i == SelectedIndex) { using SolidBrush sb = new(ForegroundColor); g.FillRectangle(sb, r); } using SolidBrush tb = new(i == SelectedIndex ? SelectedTextColor : UnselectedTextColor); g.DrawString(TabPages[i].Text, Font, tb, r, _mth.SetPosition()); } break; case TabStyle.Style2: for (int i = 0; i <= TabCount - 1; i++) { Rectangle r = GetTabRect(i); if (i == SelectedIndex) { using Pen sb = new(ForegroundColor, 2); g.DrawLine(sb, r.X, r.Height, r.X + r.Width, r.Height); } using SolidBrush tb = new(i == SelectedIndex ? SelectedTextColor : UnselectedTextColor); g.DrawString(TabPages[i].Text, Font, tb, r, _mth.SetPosition()); } break; } } #endregion Draw Control #region Events protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); for (int i = 0; i <= TabCount - 1; i++) { Rectangle r = GetTabRect(i); if (!r.Contains(e.Location)) { continue; } if (MCursor != Cursor) { Cursor = MCursor; } Invalidate(); } } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); if (MCursor == Cursor) { Cursor = Cursors.Default; } Invalidate(); } protected override void WndProc(ref Message m) { //_utl.SmoothCursor(ref m); _utl.SmoothCursor(ref m, Cursor); //_utl.NormalCursor(ref m, Cursor); base.WndProc(ref m); } #region Animation private int _oldIndex; private void DoSlideAnimate(System.Windows.Forms.TabPage control1, System.Windows.Forms.TabPage control2, bool moveback) { _utl.InitControlHandle(control1); _utl.InitControlHandle(control2); _slideGraphics = Graphics.FromHwnd(control2.Handle); _slideBitmap = new(control1.Width + control2.Width, control1.Height + control2.Height); if (moveback) { control2.DrawToBitmap(_slideBitmap, new Rectangle(0, 0, control2.Width, control2.Height)); control1.DrawToBitmap(_slideBitmap, new Rectangle(control2.Width, 0, control1.Width, control1.Height)); } else { control1.DrawToBitmap(_slideBitmap, new Rectangle(0, 0, control1.Width, control1.Height)); control2.DrawToBitmap(_slideBitmap, new Rectangle(control1.Width, 0, control2.Width, control2.Height)); } if (ControlsVisible) { foreach (Control c in control2.Controls) { c.Hide(); } } _slideAnimator.Update = (alpha) => { _slideGraphics.DrawImage(_slideBitmap, alpha); }; _slideAnimator.Complete = () => { SelectedTab = control2; if (ControlsVisible) { foreach (Control c in control2.Controls) { c.Show(); } } }; _slideAnimator.Start ( AnimateTime, new Point(moveback ? -control2.Width : 0, 0), new Point(moveback ? 0 : -control1.Width, 0), AnimateEasingType ); } protected override void OnSelecting(TabControlCancelEventArgs e) { if (!UseAnimation) { return; } if (_slideAnimator.Active) { e.Cancel = true; return; } DoSlideAnimate(TabPages[_oldIndex], TabPages[e.TabPageIndex], _oldIndex > e.TabPageIndex); } protected override void OnDeselecting(TabControlCancelEventArgs e) { _oldIndex = e.TabPageIndex; } private void DoAnimationScrollRight(Control control1, Control control2) { Graphics g = control1.CreateGraphics(); Bitmap p1 = new(control1.Width, control1.Height); Bitmap p2 = new(control2.Width, control2.Height); control1.DrawToBitmap(p1, new Rectangle(0, 0, control1.Width, control1.Height)); control2.DrawToBitmap(p2, new Rectangle(0, 0, control2.Width, control2.Height)); if (ControlsVisible) { foreach (Control c in control1.Controls) { c.Hide(); } } int slide = control1.Width - (control1.Width % Speed); int a; for (a = 0; a >= -slide; a += -Speed) { g.DrawImage(p1, new Rectangle(a, 0, control1.Width, control1.Height)); g.DrawImage(p2, new Rectangle(a + control2.Width, 0, control2.Width, control2.Height)); } a = control1.Width; g.DrawImage(p1, new Rectangle(a, 0, control1.Width, control1.Height)); g.DrawImage(p2, new Rectangle(a + control2.Width, 0, control2.Width, control2.Height)); SelectedTab = (System.Windows.Forms.TabPage)control2; if (ControlsVisible) { foreach (Control c in control2.Controls) { c.Show(); } foreach (Control c in control1.Controls) { c.Show(); } } } #endregion Animation #endregion Events #region Methods private void InvalidateTabPage(Color c) { foreach (MetroTabPage T in TabPages) { T.Style = Style; T.BaseColor = c; T.Invalidate(); } } #endregion } #endregion }