using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using ryControls.Win32API;

namespace ryControls
{
    /// <summary>
    /// Chrome风格的多标签控件
    /// </summary>
    public partial class ChromeTabControl : TabControl
    {
        private Rectangle addRec;
        private Color colorMouseOn = Color.Silver;

        private Image close_Image;
        private Image close_normalImage;
        private Image TabIcon;

        private Rectangle rectClose;
        private Rectangle rectIcon;
        private Rectangle rectFont;
        private Color onSelectedColor1 = Color.White;
        private Color onSelectedColor2 = Color.White;
        private Color offSelectedColor1 = Color.FromArgb(192, 255, 255);
        private Color offSelectedColor2 = Color.FromArgb(200, 66, 204, 255);
        private Color MoveSelectedColor1 = Color.FromArgb(200, 66, 204, 255);
        private Color MoveSelectedColor2 = Color.FromArgb(192, 255, 255);
        private Color BottomLineColor = Color.FromArgb(188, 188, 188);
        private SolidBrush brushFont = new SolidBrush(Color.Black);
        private Color backcolor = System.Drawing.SystemColors.Control;
        private Image _backgroundImage = null;
        private Rectangle rctTabHeaderColor;
        private Rectangle rctTabHeaderImage;
        private int tabIndex = 0;
        private int OverIndex = -1;
        private int tabid = 0;
        private bool AllSelected = false;
        private Point tabPoint;
        private TabPage _SourceTabPage = null;
        private int _tabHOffset = 0;

        /// <summary>
        /// 设置选项卡处于选中状态时第一背景色.
        /// </summary>
        [Description("设置选项卡处于选中状态时第一背景色。")]
        [DefaultValue(typeof(Color), "White")]
        [Browsable(true)]
        public Color TabOnColorStart
        {
            get { return onSelectedColor1; }
            set
            {
                if (!value.Equals(onSelectedColor1))
                {
                    onSelectedColor1 = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置选项卡处于选中状态时第二背景色.
        /// </summary>
        [Description("设置选项卡处于选中状态时第二背景色。")]
        [DefaultValue(typeof(Color), "White")]
        [Browsable(true)]
        public Color TabOnColorEnd
        {
            get { return onSelectedColor2; }
            set
            {
                if (!value.Equals(onSelectedColor2))
                {
                    onSelectedColor2 = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置选项卡处于非选中状态时第一背景色.
        /// </summary>
        [Description("设置选项卡处于非选中状态时第一背景色。")]
        [DefaultValue(typeof(Color), "192, 255, 255")]
        [Browsable(true)]
        public Color TabOffColorStart
        {
            get { return offSelectedColor1; }
            set
            {
                if (!value.Equals(offSelectedColor1))
                {
                    offSelectedColor1 = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置选项卡处于非选中状态时第二背景色.
        /// </summary>
        [Description("设置选项卡处于非选中状态时第二背景色。")]
        [DefaultValue(typeof(Color), "200, 66, 204, 255")]
        [Browsable(true)]
        public Color TabOffColorEnd
        {
            get { return offSelectedColor2; }
            set
            {
                if (!value.Equals(offSelectedColor2))
                {
                    offSelectedColor2 = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置鼠标移动到非选中状态选项卡时第一背景色.
        /// </summary>
        [Description("设置鼠标移动到非选中状态选项卡时第一背景色。")]
        [DefaultValue(typeof(Color), "200, 66, 204, 255")]
        [Browsable(true)]
        public Color TabMoveColorStart
        {
            get { return MoveSelectedColor1; }
            set
            {
                if (!value.Equals(MoveSelectedColor1))
                {
                    MoveSelectedColor1 = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置鼠标移动到非选中状态选项卡时第二背景色.
        /// </summary>
        [Description("设置鼠标移动到非选中状态选项卡时第二背景色。")]
        [DefaultValue(typeof(Color), "192, 255, 255")]
        [Browsable(true)]
        public Color TabMoveColorEnd
        {
            get { return MoveSelectedColor2; }
            set
            {
                if (!value.Equals(MoveSelectedColor2))
                {
                    MoveSelectedColor2 = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置选项卡工作区背景色.
        /// </summary>
        [Description("设置选项卡工作区背景色。")]
        [DefaultValue(typeof(Color), "Control")]
        [Browsable(true)]
        public Color BackTabPageColor
        {
            get { return backcolor; }
            set
            {
                if (!value.Equals(backcolor))
                {
                    backcolor = value;
                    Invalidate();
                    Update();
                }
            }
        }

        /// <summary>
        /// 设置选项卡工作区背景图.
        /// </summary>
        [Description("设置选项卡工作区背景图。")]
        [Browsable(true)]
        public Image BackTabPageImage
        {
            get
            {
                return _backgroundImage;
            }
            set
            {
                if (value != null)
                {
                    if (!value.Equals(_backgroundImage))
                    {
                        _backgroundImage = value;
                        Invalidate();
                        Update();
                    }
                }
                else
                {
                    _backgroundImage = null;
                    Invalidate();
                    Update();
                }
            }
        }
        private bool _ShowCloseButton = true;
        /// <summary>
        /// 是否显示关闭按钮                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        /// </summary>
        [Description("是否显示关闭按钮")]
        public bool ShowCloseButton
        {
            get { return _ShowCloseButton; }
            set { _ShowCloseButton = value; Invalidate(); Update(); }
        }
        private bool _ShowAddButton = true;
        /// <summary>
        /// 是否显示新增按钮                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        /// </summary>
        [Description("是否显示新增按钮")]
        public bool ShowAddButton
        {
            get { return _ShowAddButton; }
            set { _ShowAddButton = value; Invalidate(); Update(); }
        }
        /// <summary>
        /// 是否允许拖拽标签                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        /// </summary>
        [Description("是否允许拖拽标签")]
        public bool AllowDragTab{get;set; } = false;
        private int _TabMaxWidth = 200;
        /// <summary>
        /// 标签最大宽度                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        /// </summary>
        [Description("标签最大宽度")]
        public int TabMaxWidth
        {
            get { return _TabMaxWidth; }
            set { _TabMaxWidth = value; Invalidate(); Update(); }
        }
        /// <summary>
        /// 标签右键菜单                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        /// </summary>
        [Description("标签右键菜单")]
        public ContextMenuStrip TabContextMenuStrip { get; set; } = null;
        /// <summary>
        /// 鼠标按下标签时激发
        /// </summary>
        [Description("鼠标按下标签时激发")]
        public event MouseEventHandler OnTabMouseDown;
        /// <summary>
        /// 鼠标放开标签时激发
        /// </summary>
        [Description("鼠标放开标签时激发")]
        public event MouseEventHandler OnTabMouseUp;
        /// <summary>
        /// Chrome风格的多标签控件
        /// </summary>
        public ChromeTabControl()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint |
                 ControlStyles.SupportsTransparentBackColor | ControlStyles.ResizeRedraw |
                 ControlStyles.UserMouse, true);

            this.ItemSize = new Size(TabMaxWidth, 25);
            this.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
            //this.AllowDrop = true; 


            //从资源文件（嵌入到程序集）里读取图片
            close_Image = new Bitmap(this.GetType(), "close.png");
            close_normalImage = new Bitmap(this.GetType(), "close_normal.png");
        }
        /// <summary>
        /// 
        /// </summary>
        ~ChromeTabControl()
        {
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g"></param>
        protected virtual void Draw(Graphics g)
        {
            DrawBorder(g);

            Rectangle rct = this.ClientRectangle;
            rct.Inflate(-1, -1);
            Rectangle rctTabArea = this.DisplayRectangle;

            if (this.TabCount > 0)
            {
                rctTabHeaderColor = new Rectangle(rct.Left, rct.Top, rct.Width, rctTabArea.Top);
                rctTabHeaderImage = new Rectangle(rct.Left - 1, rct.Top - 1, rct.Width + 3, rctTabArea.Top);
            }
            else
            {
                rctTabHeaderColor = new Rectangle(rct.Left, rct.Top, rct.Width, rctTabArea.Top + 24);
                rctTabHeaderImage = new Rectangle(rct.Left - 1, rct.Top - 1, rct.Width + 3, rctTabArea.Top + 25);
            }

            using (Bitmap overlay = new Bitmap(rctTabHeaderImage.Width, rctTabHeaderImage.Height))
            {
                using (Graphics gr = Graphics.FromImage(overlay))
                {
                    gr.SmoothingMode = SmoothingMode.HighQuality;

                    if (_backgroundImage != null)
                    {
                        using (Brush brush = new TextureBrush(_backgroundImage, WrapMode.TileFlipXY))
                            gr.FillRectangle(brush, 0, 0, overlay.Width, overlay.Height);
                    }
                    else
                    {
                        g.FillRectangle(new SolidBrush(backcolor), 0, 0, rctTabHeaderColor.Width + 2, rctTabHeaderColor.Height);
                    }
                }

                g.DrawImage(overlay, rctTabHeaderImage, 1, 1, overlay.Width, overlay.Height, GraphicsUnit.Pixel);
                g.DrawLine(new Pen(new SolidBrush(BottomLineColor), 1), 0, 28, this.ClientSize.Width, 28);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g"></param>
        protected virtual void DrawBorder(Graphics g)
        {
            Rectangle rct = this.ClientRectangle;
            Rectangle rctTabArea = this.DisplayRectangle;

            using (Pen pen = new Pen(Color.Silver))
            {
                pen.DashStyle = DashStyle.Solid;

                g.DrawLine(pen, rct.X, rctTabArea.Y, rct.X, rct.Bottom - 1);
                g.DrawLine(pen, rct.X, rct.Bottom - 1, rct.Width - 1, rct.Bottom - 1);
                g.DrawLine(pen, rct.Width - 1, rct.Bottom - 1, rct.Width - 1, rctTabArea.Y);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rect"></param>
        /// <param name="title"></param>
        /// <param name="selected"></param>
        /// <param name="mouseOver"></param>
        protected virtual void DrawAll(Graphics g, Rectangle rect, string title, bool selected, bool mouseOver)
        {
            try
            {
                rectFont = new Rectangle(rect.X + TabStrLeftMargin, rect.Y + 9, rect.Width - 30, rect.Height - TabStrLeftMargin);
                rectClose = new Rectangle(rect.X + rect.Width - 25, 11, 12, 12);
                if(!ShowCloseButton)
                {
                    rectFont.Width += 10;
                }
                bool haveIcon = false;
                for (int i = 0; i < this.TabCount; i++)
                {
                    var rect2 = this.GetTabRect(i);
                    if (this.ImageList != null && !this.TabPages[i].ImageIndex.Equals(-1))
                    {
                        if (this.TabPages[i].ImageIndex <= this.ImageList.Images.Count - 1)
                        {
                            TabIcon = this.ImageList.Images[this.TabPages[i].ImageIndex];
                            rectIcon = new Rectangle(rect2.X + 16, 8, 16, 16);
                            DrawTabIcon(g, rectIcon);
                            TabIcon.Dispose();
                            haveIcon = true;
                        }
                    }
                }
                if(haveIcon)
                {
                    rectFont.X += 7;
                    if (ShowCloseButton)
                    {
                        rectFont.Width -= 10;
                    }
                }
                DrawRect(g, rect, selected, mouseOver);
                DrawString(g, rectFont, title, Font);
                DrawClose(g, rectClose, CloseHitTest(this.PointToClient(Cursor.Position)));
            }
            catch { }
        }
        private int _radius = 15;                        //圆角半径
        /// <summary>
        ///设置圆角半径 
        /// </summary>
        [Description("圆角半径")]
        [DefaultValue(15)]//设置圆角半径，默认值为8，最小值为4px
        public int Radius
        {
            get { return _radius; }
            set
            {
                if (_radius != value)
                {
                    _radius = value < 4 ? 4 : value;
                    base.Invalidate();
                }
            }
        }
        private int _FontLeft = 10;                        //Tab文字左边距离
        /// <summary>
        ///Tab文字左边距离 
        /// </summary>
        [Description("Tab文字左边距离")]
        [DefaultValue(10)]//
        public int TabStrLeftMargin
        {
            get { return _FontLeft; }
            set
            {
                if (_FontLeft != value)
                {
                    _FontLeft = value < 4 ? 4 : value;
                    base.Invalidate();
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rect"></param>
        /// <param name="selected"></param>
        /// <param name="mouseOver"></param>
        protected virtual void DrawRect(Graphics g, Rectangle rect, bool selected, bool mouseOver)
        {
            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddBezier(
                    new Point(rect.X, rect.Bottom + 2),
                    new Point(rect.X + 3, rect.Bottom - 2),
                    new Point(rect.X + 3, rect.Bottom - 2),
                    new Point(rect.X, rect.Bottom + 2));
                //path.AddLine(rect.X + 4, rect.Bottom - 4, rect.Left + 15 - 4, rect.Y + 4);
                path.AddBezier(
                    new Point(rect.Left + _radius - 4, rect.Y + 4),
                    new Point(rect.Left + _radius - 3, rect.Y + 2),
                    new Point(rect.Left + _radius - 3, rect.Y + 2),
                    new Point(rect.Left + _radius, rect.Y));
                //path.AddLine(rect.Left + 15, rect.Y, rect.Right - 15, rect.Y);
                path.AddBezier(
                    new Point(rect.Right - _radius, rect.Y),
                    new Point(rect.Right - _radius + 3, rect.Y + 2),
                    new Point(rect.Right - _radius + 3, rect.Y + 2),
                    new Point(rect.Right - _radius + 4, rect.Y + 4));
                //path.AddLine(rect.Right - 15 + 4, rect.Y + 4, rect.Right - 4, rect.Bottom - 4);
                path.AddBezier(
                    new Point(rect.Right, rect.Bottom),
                    new Point(rect.Right - 3, rect.Bottom - 3),
                    new Point(rect.Right - 3, rect.Bottom - 3),
                    new Point(rect.Right + 1, rect.Bottom + 1));

                Region region = new System.Drawing.Region(path);

                g.DrawPath(new Pen(Color.Gray), path);

                if (mouseOver)
                {
                    using (LinearGradientBrush brush = new LinearGradientBrush(rect, MoveSelectedColor1, MoveSelectedColor2, LinearGradientMode.Vertical))
                    {
                        g.FillPath(brush, path);
                    }
                    //g.FillPath(new SolidBrush(MoveSelectedColor), path);
                }
                else
                {
                    using (LinearGradientBrush brush = selected ? new LinearGradientBrush(rect, onSelectedColor1, onSelectedColor2, LinearGradientMode.Vertical) : new LinearGradientBrush(rect, offSelectedColor1, offSelectedColor2, LinearGradientMode.Vertical))
                    {
                        g.FillPath(brush, path);
                    }
                    //g.FillPath(new SolidBrush(selected ? onSelectedColor : offSelectedColor), path);
                }
                g.DrawLine(new Pen(selected ? onSelectedColor2 : BottomLineColor, 1), rect.X + 1, rect.Bottom + 1, rect.Right, rect.Bottom + 1);
            }
        }
        /// <summary>
        /// 画标签文字
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rect"></param>
        /// <param name="title"></param>
        /// <param name="font"></param>
        protected virtual void DrawString(Graphics g, Rectangle rect, string title, Font font)
        {
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            g.DrawString(title, font, brushFont, rect, format);
        }
        /// <summary>
        /// 画标签图标
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rect"></param>
        protected virtual void DrawTabIcon(Graphics g, Rectangle rect)
        {
            g.DrawImageUnscaled(TabIcon, rect);
        }
        /// <summary>
        /// 画关闭按钮
        /// </summary>
        /// <param name="g"></param>
        /// <param name="rect"></param>
        /// <param name="mouseOn"></param>
        protected virtual void DrawClose(Graphics g, Rectangle rect, bool mouseOn)
        {
            if (ShowCloseButton)
            {
                if (mouseOn)
                    g.DrawImage(close_Image, rect);
                else
                    g.DrawImage(close_normalImage, rect);
            }
        }

        private bool CloseHitTest(Point cltPosition)
        {
            return rectClose.Contains(cltPosition);
        }
        /// <summary>
        /// 获取所有选项卡合起来的宽度
        /// </summary>
        /// <returns></returns>
        private int GetTabTotalWidth()
        {
            return this.ItemSize.Width * this.TabCount;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Draw(e.Graphics);
            Graphics g = e.Graphics;

            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.CompositingQuality = CompositingQuality.HighQuality;
            if (this.TabCount > 0)
            {
                if (GetTabTotalWidth() + 30 > this.ClientSize.Width || (this.ClientSize.Width - 30) / (this.TabCount) > this.ItemSize.Width)
                {
                    if (this.ClientSize.Width < GetTabTotalWidth() + 30 || this.ItemSize.Width < TabMaxWidth)
                    {
                        if (this.TabCount > 0)
                        {
                            this.ItemSize = new Size((this.ClientSize.Width - 30) / (this.TabCount), 25);
                        }
                    }

                    if (this.ItemSize.Width > TabMaxWidth)
                    {
                        this.ItemSize = new Size(TabMaxWidth, 25);
                    }
                }

                addRec = new Rectangle(GetTabTotalWidth() + 5, 8, 16, 16); //指定显示区域的位置的大小
                if (ShowAddButton)
                {
                    e.Graphics.FillEllipse(new SolidBrush(colorMouseOn), addRec);

                    e.Graphics.DrawLine(new Pen(Color.White, 1.55f), GetTabTotalWidth() + 8, 16, GetTabTotalWidth() + 18, 16);
                    e.Graphics.DrawLine(new Pen(Color.White, 1.55f), GetTabTotalWidth() + 13, 11, GetTabTotalWidth() + 13, 21);
                }
                for (int i = 0; i < this.TabCount; i++)
                {
                    if (tabIndex != 0)
                    {
                        if (tabIndex < this.TabCount)
                        {
                            if (tabIndex == i)
                            {
                                this.SelectedIndex = i;
                                DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, true, false);
                            }
                            else
                            {
                                if (OverIndex == i)
                                {
                                    DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, false, true);
                                }
                                else
                                {
                                    DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, false, false);
                                }
                            }
                        }
                        else
                        {
                            if ((tabIndex - 1) == i)
                            {
                                this.SelectedIndex = i;
                                DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, true, false);
                            }
                            else
                            {
                                if (OverIndex == i)
                                {
                                    DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, false, true);
                                }
                                else
                                {
                                    DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, false, false);
                                }
                            }
                        }
                    }
                    else
                    {
                        if (this.SelectedIndex == i)
                        {
                            DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, true, false);
                        }
                        else
                        {
                            if (OverIndex == i)
                            {
                                DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, false, true);
                            }
                            else
                            {
                                DrawAll(g, this.GetTabRect(i), this.TabPages[i].Text, false, false);
                            }
                        }
                    }
                }
                tabIndex = 0;
            }
            else
            {
                tabIndex = 0;
                addRec = new Rectangle(10, 8, 16, 16); //指定显示区域的位置的大小
                if (ShowAddButton)
                {
                    e.Graphics.FillEllipse(new SolidBrush(colorMouseOn), addRec);

                    e.Graphics.DrawLine(new Pen(Color.White, 1.55f), 10 + 3, 16, 10 + 13, 16);
                    e.Graphics.DrawLine(new Pen(Color.White, 1.55f), 10 + 8, 11, 10 + 8, 21);
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

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

            if (m.Msg == (int)ryControls.Win32API.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;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.Button == MouseButtons.Left)
            {
                this._SourceTabPage = OverTab();

                tabPoint = new Point(e.X, e.Y);

                if (addRec.Contains(e.Location))
                {
                    colorMouseOn = Color.Orange;
                }
            }
            if (this.TabCount > 0)
            {
                for (int i = 0; i < this.TabCount; i++)
                {
                    Rectangle tabRect = new Rectangle(this.GetTabRect(i).X + this.GetTabRect(i).Width - 25, 11, 12, 12);
                    if (tabRect.Contains(e.Location))
                    {
                        OnTabMouseDown?.Invoke(this, e);
                        break;
                    }
                }
                
            }
            this.Invalidate();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            
            if (e.Button == MouseButtons.Left)
            {
                bool AscendingMove = false;

                if (ShowAddButton && addRec.Contains(e.Location))
                {
                    colorMouseOn = Color.FromArgb(229, 233, 227);
                    AddTabPage("tabPage" + (this.TabCount + 1).ToString());
                }

                if (this.TabCount > 0)
                {
                    if (!AllSelected)
                    {
                        Rectangle tabRect = new Rectangle(this.GetTabRect(this.SelectedIndex).X + this.GetTabRect(this.SelectedIndex).Width - 25, 11, 12, 12);

                        if (tabRect.Contains(e.Location))
                        {
                            AscendingMove = true;
                            OnTabMouseUp?.Invoke(this, e);
                            if (ShowCloseButton)
                            {
                                tabIndex = this.SelectedIndex;
                                this.TabPages.Remove(this.SelectedTab);
                            }
                        }
                        else
                        {
                            AscendingMove = false;
                        }
                    }
                    else
                    {
                        Rectangle tabRect = new Rectangle(this.GetTabRect(tabid).X + this.GetTabRect(tabid).Width - 25, 11, 12, 12);

                        if (tabRect.Contains(e.Location))
                        {
                            OnTabMouseUp?.Invoke(this, e);
                            AscendingMove = true;
                            if (ShowCloseButton)
                            {
                                this.TabPages.RemoveAt(tabid);
                            }
                            AllSelected = false;
                        }
                        else
                        {
                            AscendingMove = false;
                        }
                    }

                    if (this._SourceTabPage != null && AllowDragTab)
                    {
                        TabPage currTabPage = GetTabPageFromXY(e.X, e.Y);

                        if ((currTabPage != null) && (!currTabPage.Equals(this._SourceTabPage)))
                        {
                            Rectangle currRect = base.GetTabRect(base.TabPages.IndexOf(currTabPage));
                            if ((base.TabPages.IndexOf(currTabPage) < base.TabPages.IndexOf(this._SourceTabPage)))
                            {
                                base.TabPages.Remove(this._SourceTabPage);
                                base.TabPages.Insert(base.TabPages.IndexOf(currTabPage), this._SourceTabPage);
                                base.SelectedTab = this._SourceTabPage;
                            }
                            else if ((base.TabPages.IndexOf(currTabPage) > base.TabPages.IndexOf(this._SourceTabPage)))
                            {
                                if (!AscendingMove)
                                {
                                    base.TabPages.Remove(this._SourceTabPage);
                                    base.TabPages.Insert(base.TabPages.IndexOf(currTabPage) + 1, this._SourceTabPage);
                                    base.SelectedTab = this._SourceTabPage;
                                }
                            }
                        }
                    }
                }
            }
            else if (e.Button == MouseButtons.Right)
            {
                if(TabContextMenuStrip!=null)
                {
                    TabContextMenuStrip.Show(MousePosition);
                }
            }
            this._SourceTabPage = null;
            base.Cursor = Cursors.Default;
            this.Invalidate();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            OverIndex = -1;
            Invalidate();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            for (int i = 0; i < this.TabCount; i++)
            {
                if (this.SelectedIndex != i && this.GetTabRect(i).Contains(e.Location))
                {
                    OverIndex = i;
                    break;
                }
                else
                {
                    OverIndex = -1;
                }
            }

            if (addRec.Contains(e.Location))
            {
                colorMouseOn = Color.OrangeRed;
            }
            else
            {
                colorMouseOn = Color.Silver;
            }

            if ((e.Button == MouseButtons.Left) && (this._SourceTabPage != null) && AllowDragTab)
            {
                TabPage currTabPage = GetTabPageFromXY(e.X, e.Y);
                if ((currTabPage != null))
                {
                    Rectangle currRect = base.GetTabRect(base.TabPages.IndexOf(currTabPage));
                    if ((base.TabPages.IndexOf(currTabPage) < base.TabPages.IndexOf(this._SourceTabPage)))
                    {
                        base.Cursor = Cursors.PanWest;
                    }
                    else if ((base.TabPages.IndexOf(currTabPage) > base.TabPages.IndexOf(this._SourceTabPage)))
                    {
                        base.Cursor = Cursors.PanEast;
                    }
                    else
                    {
                        base.Cursor = Cursors.Default;
                    }
                }
                else
                {
                    this.Cursor = Cursors.No;
                }
            }
            else
            {
                this.Cursor = Cursors.Default;
            }

            this.Invalidate();
        }

        private TabPage GetTabPageFromXY(int x, int y)
        {
            for (int i = 0; i <= base.TabPages.Count - 1; i++)
            {
                if (base.GetTabRect(i).Contains(x, y))
                {
                    return base.TabPages[i];
                }
            }
            return null;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSelecting(TabControlCancelEventArgs e)
        {
            base.OnSelecting(e);

            if (OverIndex > -1)
            {
                Rectangle tabRect = new Rectangle(this.GetTabRect(e.TabPageIndex).X + this.GetTabRect(e.TabPageIndex).Width - 25, 11, 12, 12);

                if (tabRect.Contains(tabPoint))
                {
                    e.Cancel = true;
                    AllSelected = true;
                    tabid = e.TabPageIndex;
                }
                else
                {
                    AllSelected = false;
                }
            }
            else
            {
                AllSelected = false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
        }
        /// <summary>
        /// 
        /// </summary>
        public override Rectangle DisplayRectangle
        {
            get
            {
                Rectangle rect = base.DisplayRectangle;
                return new Rectangle(rect.Left - 3, rect.Top, rect.Width + 6, rect.Height + 3);
            }
        }
        /// <summary>
        /// 添加新标签
        /// </summary>
        /// <param name="tabName"></param>
        public void AddTabPage(string tabName)
        {
            TabPages.Add(tabName);
            SelectTab(TabPages.Count - 1);
            this.SelectedTab.AutoScroll = true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual TabPage OverTab()
        {
            TabPage over = null;

            Point pt = this.PointToClient(Cursor.Position);
            ryControls.Win32API.User32.TCHITTESTINFO mouseInfo = new ryControls.Win32API.User32.TCHITTESTINFO(pt, ryControls.Win32API.User32.TabControlHitTest.TCHT_ONITEM);
            int currentTabIndex = ryControls.Win32API.User32.SendMessage(this.Handle, ryControls.Win32API.User32._TCM_HITTEST, IntPtr.Zero, ref mouseInfo);

            if (currentTabIndex > -1)
            {
                Rectangle currentTabRct = this.GetTabRect(currentTabIndex);

                if (currentTabIndex == 0)
                    currentTabRct.X += _tabHOffset;

                if (currentTabRct.Contains(pt))
                    over = this.TabPages[currentTabIndex] as TabPage;
            }

            return over;
        }
    }
}
