SurTrack.cs 11.4 KB
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Asa.Face
{
    /// <summary>
    /// 滑轨控件
    /// </summary>
    [DefaultProperty("Value")]
    [DefaultEvent("ValueChanged")]
    public partial class SurTrack : BaseCtl
    {
        private GraphicsPath _trackPath;  //轨道路径
        private GraphicsPath _trackCurrPath;
        private RectangleF _adjustRect;    //调节器
        private GraphicsPath _adjustPath;
        private RectangleF _textRect;
        private bool _adjustDown;
        private int _min = 0;
        private int _max = 100;
        private int _value = 0;
        private float _len;
        private float _step;
        private  int _radius;        //半径
        private int _diameter = 10;  //直径
        private Appearance _appearance = Appearance.LeftRight;

        private const int SPACE = 6;

        /// <summary>
        /// 滑轨控件
        /// </summary>
        public SurTrack()
        {
            InitializeComponent();
        }


        //==========事件==========
        /// <summary>
        /// 当前值改变时发生的事件
        /// </summary>
        [Browsable(true), Category(""), Description("当前值改变时发生的事件")]
        public event MyEvent.Changed ValueChanged;


        //==========属性==========
        /// <summary>
        /// 控件的外观
        /// </summary>
        [Browsable(true), Category(""), Description("控件的外观"), DefaultValue(Appearance.LeftRight)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public Appearance Appearance
        {
            set
            {
                _appearance = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _appearance;
            }
        }

        /// <summary>
        /// 最小值
        /// </summary>
        [Browsable(true), Category(""), Description("最小值"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Min
        {
            set
            {
                _min = value;
                if (_value < _min) _value = _min;
                CalcSize();
                Refresh();
            }
            get
            {
                return _min;
            }
        }

        /// <summary>
        /// 最大值
        /// </summary>
        [Browsable(true), Category(""), Description("最大值"), DefaultValue(100)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Max
        {
            set
            {
                _max = value;
                if (_value > _max) _value = _max;
                CalcSize();
                Refresh();
            }
            get
            {
                return _max;
            }
        }

        /// <summary>
        /// 当前值
        /// </summary>
        [Browsable(true), Category(""), Description("当前值"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Value
        {
            set
            {
                _value = value;
                if (_value < _min)
                    _value = _min;
                else if (_value > _max)
                    _value = _max;
                CalcSize();
                Refresh();
                ValueChanged?.Invoke(this);
            }
            get
            {
                return _value;
            }
        }

        /// <summary>
        /// 轨道宽度
        /// </summary>
        [Browsable(true), Category(""), Description("轨道宽度"), DefaultValue(8)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int TrackWidth
        {
            set
            {
                if (value > 0)
                    _diameter = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _diameter;
            }
        }


        //==========私有==========
        /// <summary>
        /// 改变大小
        /// </summary>
        protected override void CalcSize()
        {
            base.CalcSize();

            _radius = _diameter / 2;
            RectangleF rect1, rect2;
            PointF pt;

            if (_appearance == Appearance.UpDown)
            {
                rect1 = new RectangleF(Width / 2f - _radius, SPACE, _diameter, _diameter);  //上半圆
                rect2 = new RectangleF(Width / 2f - _radius, Height - SPACE - _diameter, _diameter, _diameter);  //下半圆
                _len = rect2.Y - rect1.Y;
                _step = _len / (_max - _min);

                //轨道
                _trackPath = new GraphicsPath();
                _trackPath.AddArc(rect1, 180, 180);
                _trackPath.AddLine(rect1.Right, rect1.Y + _radius, rect2.Right, rect2.Y + _radius);
                _trackPath.AddArc(rect2, 0, 180);
                _trackPath.AddLine(rect2.X, rect2.Y + _radius, rect1.X, rect1.Y + _radius);

                //轨道当前部分
                pt = new PointF(rect1.X + _radius, rect1.Y + _radius + (_value - _min) * _step);
                _trackCurrPath = new GraphicsPath();
                _trackCurrPath.AddArc(rect1, 180, 180);
                _trackCurrPath.AddLine(rect1.Right, rect1.Y + _radius, pt.X + _radius, pt.Y);
                _trackCurrPath.AddLine(pt.X + _radius, pt.Y, pt.X - _radius, pt.Y);
                _trackCurrPath.AddLine(pt.X - _radius, pt.Y, rect1.X, rect1.Y + _radius);

                //调节器
                int r = 8;
                _adjustRect = new RectangleF(pt.X - _radius - r, pt.Y - r, _diameter + r + r, r + r);
                rect1 = new RectangleF(pt.X - _radius - r, pt.Y - r, r * 2, r * 2);
                rect2 = new RectangleF(pt.X + _radius - r, pt.Y - r, r * 2, r * 2);
                _adjustPath = new GraphicsPath();
                _adjustPath.AddArc(rect1, 90, 180);
                _adjustPath.AddLine(rect1.X + r, rect1.Y, rect2.X + r, rect2.Y);
                _adjustPath.AddArc(rect2, -90, 180);
                _adjustPath.AddLine(rect2.X + r, rect2.Bottom, rect1.X + r, rect1.Bottom);

                //数值显示
                SizeF sf = CreateGraphics().MeasureString(_value.ToString(), Common.FONT_SONG9);
                _textRect = new RectangleF(_adjustRect.X + (_adjustRect.Width - sf.Width) / 2f + 1, _adjustRect.Y + (_adjustRect.Height - sf.Height) / 2f + 1, sf.Width, sf.Height);
            }
            else if (_appearance == Appearance.LeftRight)
            {
                rect1 = new RectangleF(SPACE, Height / 2f - _radius, _diameter, _diameter);  //左半圆
                rect2 = new RectangleF(Width - SPACE - _diameter, Height / 2f - _radius, _diameter, _diameter);  //右半圆
                _len = rect2.X - rect1.X;
                _step = _len / (_max - _min);

                //轨道
                _trackPath = new GraphicsPath();
                _trackPath.AddArc(rect1, 90, 180);
                _trackPath.AddLine(rect1.X + _radius, rect1.Y, rect2.X + _radius, rect2.Y);
                _trackPath.AddArc(rect2, -90, 180);
                _trackPath.AddLine(rect2.X + _radius, rect2.Bottom, rect1.X + _radius, rect1.Bottom);

                //轨道当前部分
                pt = new PointF(rect1.X + _radius + (_value - _min) * _step, rect1.Y + _radius);
                _trackCurrPath = new GraphicsPath();
                _trackCurrPath.AddArc(rect1, 90, 180);
                _trackCurrPath.AddLine(rect1.X + _radius, rect1.Y, pt.X, pt.Y - _radius);
                _trackCurrPath.AddLine(pt.X, pt.Y - _radius, pt.X, pt.Y + _radius);
                _trackCurrPath.AddLine(pt.X, pt.Y + _radius, rect1.X + _radius, rect1.Bottom);

                //调节器
                int r = 8;
                _adjustRect = new RectangleF(pt.X - r, pt.Y - _radius - r, r + r, _diameter + r + r);
                rect1 = new RectangleF(pt.X - r, pt.Y - _radius - r, r * 2, r * 2);
                rect2 = new RectangleF(pt.X - r, pt.Y + _radius - r, r * 2, r * 2);
                _adjustPath = new GraphicsPath();
                _adjustPath.AddArc(rect1, 180, 180);
                _adjustPath.AddLine(rect1.Right, rect1.Y + r, rect2.Right, rect2.Y + r);
                _adjustPath.AddArc(rect2, 0, 180);
                _adjustPath.AddLine(rect2.X, rect2.Y + r, rect1.X, rect1.Y + r);
            }
        }

        private void FlatTrack_Paint(object sender, PaintEventArgs e)
        {
            BufferedGraphicsContext current = BufferedGraphicsManager.Current;
            BufferedGraphics bg = current.Allocate(e.Graphics, e.ClipRectangle);
            Graphics g = bg.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.Clear(Common.BACK_COLOR);  //背景

            if (Inside && Enabled)
            {
                if (BorderWidth > 0)
                    g.DrawRectangle(BorderInsidePen, BorderRect);

            }
            else
            {
                if (BorderWidth > 0)
                    g.DrawRectangle(BorderOutsidePen, BorderRect);
               
            }

            if (Enabled)
            {
                g.DrawPath(Common.FORE_PEN, _trackPath);
                g.FillPath(Common.BLUE_BRUSH, _trackCurrPath);
                if (_adjustDown)
                    g.FillPath(Common.BLUE_BRUSH, _adjustPath);
                else
                    g.FillPath(Common.FORE_BRUSH, _adjustPath);
            }
            else
            {
                g.DrawPath(Common.BORDER_PEN, _trackPath);
                g.FillPath(Common.BORDER_BRUSH, _adjustPath);
            }


         

            if (_appearance == Appearance.UpDown)
                g.DrawString(_value.ToString(), Common.FONT_SONG9, Common.BACK_BRUSH, _textRect);


            bg.Render();
            bg.Dispose();
        }

        private void FlatTrack_MouseDown(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (e.Button == MouseButtons.Left)
            {
                bool rtn = _adjustRect.Contains(e.Location);
                if (rtn != _adjustDown)
                {
                    _adjustDown = rtn;
                    Refresh();
                }
            }
        }

        private void FlatTrack_MouseMove(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (_adjustDown)
            {
                int tt = 0;
                if (_appearance == Appearance.UpDown)
                    tt = e.Y;
                else if (_appearance == Appearance.LeftRight)
                    tt = e.X;

                float val = (tt - SPACE - _radius) / _step + _min;
                int n = (int)val;
                if (n == _value) return;
                Value = n;
            }
        }

        private void FlatTrack_MouseUp(object sender, MouseEventArgs e)
        {
            if (!Enabled) return;
            if (_adjustDown)
            {
                _adjustDown = false;
                Refresh();
            }
        }

    }
}