FaceTrackBar.cs 9.3 KB
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace FaceControl
{
    [DefaultProperty("Value")]
    [DefaultEvent("Scroll")]
    public partial class FaceTrackBar : ControlBase
    {
        private bool mouseDown = false;
        private bool buttonOver = false;
        private float trackStep = 0;
        private GraphicsPath borderPath = new GraphicsPath();
        private GraphicsPath slidePath = new GraphicsPath();
        private RectangleF trackActual = new RectangleF();

        private int _trackHeight = 14;
        private int _min = 0;
        private int _max = 100;
        private int _value = 0;

        private const int SLIDE_WIDTH = 14;

        public FaceTrackBar()
        {
            InitializeComponent();
        }


        #region 事件
        [Browsable(true), Category("行为"), Description("移动滑块时发生")]
        public new event EventHandler Scroll;
        #endregion


        #region 属性
        [Browsable(true), Category("外观"), Description("控件的轨道高度"), DefaultValue(14)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int TrackHeight
        {
            get => _trackHeight;
            set
            {
                _trackHeight = value;
                CalcSize();
                Refresh();
            }
        }

        [Browsable(true), Category("行为"), Description("滑块位置的最小值"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Minimum
        {
            get => _min;
            set
            {
                _min = value;
                if (_value < _min) _value = _min;
                CalcSize();
                Refresh();
            }
        }

        [Browsable(true), Category("行为"), Description("滑块位置的最大值"), DefaultValue(100)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Maximum
        {
            get => _max;
            set
            {
                _max = value;
                if (_value > _max) _value = _max;
                CalcSize();
                Refresh();
            }
        }

        [Browsable(true), Category("行为"), Description("滑块的位置"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Value
        {
            get => _value;
            set
            {
                if (_value == value) return;
                _value = value;
                if (_value < _min)
                    _value = _min;
                else if (_value > _max)
                    _value = _max;
                CalcSize();
                Refresh();
                Scroll?.Invoke(this, new EventArgs());
            }
        }
        #endregion


        protected override void CalcSize()
        {
            base.CalcSize();
            CalcShape();
            CalcSlideLocation();
        }

        protected override void DrawEnabled(Graphics g)
        {
            base.DrawEnabled(g);

            //填充当前的值
            Region reg = new Region(borderPath);
            reg.Intersect(trackActual);
            g.FillRegion(new SolidBrush(theme.DOWN_COLOR), reg);

            //控件边框
            if (CursorInside && buttonOver)
            {
                
               

                //if (mouseDown)
                //    g.FillPath(new SolidBrush(theme.DOWN_COLOR), borderPath);  //按下
                //else
                //    g.FillPath(new SolidBrush(theme.OVER_COLOR), borderPath);  //经过

                if (BorderWidth > 0)
                    g.DrawPath(borderInsidePen, borderPath);
                //滑块
                if (mouseDown)
                {
                    g.FillPath(new SolidBrush(theme.DOWN_COLOR), slidePath);
                }
                else
                {
                    g.FillPath(new SolidBrush(theme.OVER_COLOR), slidePath);
                    g.DrawPath(new Pen(theme.DOWN_COLOR, 2), slidePath);
                }
            }
            else
            {
                if (BorderWidth > 0)
                    g.DrawPath(borderOutsidePen, borderPath);
                //滑块
                g.FillPath(new SolidBrush(theme.BACK_COLOR), slidePath);
                g.DrawPath(new Pen(theme.DOWN_COLOR, 2), slidePath);
            }

         
        }

        protected override void DrawDisabled(Graphics g)
        {
            base.DrawDisabled(g);

            //控件边框
            if (BorderWidth > 0)
                g.DrawPath(borderOutsidePen, borderPath);
            g.FillPath(new SolidBrush(theme.LOST_FOCUS_COLOR), slidePath);
        }


        private void CalcShape()
        {
            borderRect.X += SLIDE_WIDTH / 2f;
            borderRect.Y = (borderRect.Height - _trackHeight) / 2f;
            borderRect.Width -= SLIDE_WIDTH;
            borderRect.Height = _trackHeight;
            borderPath = new GraphicsPath();
            float n;

            switch (FaceShape)
            {
                case Model.ButtonShape.Rectangle:
                    borderPath.AddRectangle(borderRect);
                    break;
                case Model.ButtonShape.RoundRectangle:
                    n = borderRect.Height / 8f;
                    borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
                    borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
                    borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
                    borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
                    borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
                    borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
                    borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
                    borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
                    break;
                case Model.ButtonShape.Ellipse:
                    borderPath.AddEllipse(borderRect);
                    break;
                case Model.ButtonShape.EllipseRectangle:
                    n = borderRect.Height / 2f;
                    borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
                    borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
                    borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
                    borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
                    break;
                case Model.ButtonShape.Circle:
                    if (borderRect.Width > borderRect.Height)
                        borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
                    else
                        borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
                    break;
            }
        }

        private void CalcSlideLocation()
        {
            trackStep = borderRect.Width / (_max - _min);
            float curr = (_value - _min) * trackStep;
            trackActual = new RectangleF(borderRect.X, borderRect.Y, curr, borderRect.Height);

            slidePath = new GraphicsPath();
            float half = SLIDE_WIDTH / 2f;
            RectangleF rect = new RectangleF(borderRect.X + curr - half, borderRect.Y - half, SLIDE_WIDTH, SLIDE_WIDTH);
            slidePath.AddArc(rect, 180, 180);
            slidePath.AddLine(borderRect.X + curr + half, borderRect.Y, borderRect.X + curr + half, borderRect.Bottom);
            rect = new RectangleF(borderRect.X + curr - half, borderRect.Bottom - half, SLIDE_WIDTH, SLIDE_WIDTH);
            slidePath.AddArc(rect, 0, 180);
            slidePath.AddLine(borderRect.X + curr - half, borderRect.Bottom, borderRect.X + curr - half, borderRect.Y);
        }

        private void FaceTrackBar_MouseDown(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (e.Button == MouseButtons.Left)
            {
                if (slidePath.IsVisible(e.Location))
                {
                    mouseDown = true;
                    Refresh();
                }
            }
        }

        private void FaceTrackBar_MouseUp(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (e.Button == MouseButtons.Left)
            {
                mouseDown = false;
                Refresh();
                //Click?.Invoke(this, new EventArgs());
            }
        }

        private void FaceTrackBar_MouseMove(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            buttonOver = borderPath.IsVisible(e.Location) || slidePath.IsVisible(e.Location);

            if (mouseDown)
            {
                float val = (e.X - borderRect.X) / trackStep;
                Value = (int)val;
            }
            Refresh();
        }



    }
}