FlatNumberBox.cs 9.8 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;

namespace Asa.Theme
{
    [DefaultValue("Value")]
    [DefaultEvent("ValueChanged")]
    public partial class FlatNumberBox : FlatBase
    {
        private bool _leftDown;  //鼠标按下
        private bool _rightDown;  //鼠标按下
        private bool _leftOver;  //鼠标经过
        private bool _rightOver;  //鼠标经过
        private Rectangle _borderRect;
        private RectangleF _textRect;
        private Rectangle _leftRect;
        private Rectangle _rightRect;
        private Point[] _leftIcon;
        private Point[] _rightIcon;

        private float _max;        //最大值
        private float _min;        //最小值
        private float _value;      //当前值
        private int _decimal;      //小数位数
        private bool _right;       //右键按下

        private const int BORDER_W = 2;

        private int _plusTime;
        private System.Threading.Thread tPlus;
        public delegate void ValueEvent(object sender);



        public FlatNumberBox()
        {
            InitializeComponent();
            this.Disposed += FlatNumberBox_Disposed;
            BackColor = Common.BACK_COLOR;
            _max = 100;
            _min = 0;
            _value = 0;
            Increment = 1;
            CalcSize();
            Refresh();

            tPlus = new System.Threading.Thread(new System.Threading.ThreadStart(Plus));
            tPlus.Start();
        }

        private void FlatNumberBox_Disposed(object sender, EventArgs e)
        {
            if (tPlus != null)
            {
                tPlus.Abort();
                tPlus = null;
            }
        }

        ~FlatNumberBox()
        {
            if (tPlus != null)
            {
                tPlus.Abort();
                tPlus = null;
            }
        }

        [Browsable(true), Category(""), Description("显示的文本的字体")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override Font Font
        {
            set
            {
                base.Font = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return base.Font;
            }
        }

        [Browsable(true), Category(""), Description("当前值"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public float Value
        {
            set
            {
                _value = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _value;
            }
        }

        [Browsable(true), Category(""), Description("最大值"), DefaultValue(100)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public float Maximum
        {
            set
            {
                _max = value;
                if (_value > _max)
                    Value = _max;
            }
            get
            {
                return _max;
            }
        }

        [Browsable(true), Category(""), Description("最小值"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public float Minimum
        {
            set
            {
                _min = value;
                if (_value < _min)
                    Value = _min;
            }
            get
            {
                return _min;
            }
        }

        [Browsable(true), Category(""), Description("显示的小数位数"), DefaultValue(0)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int DecimalPlaces
        {
            set
            {
                _decimal = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _decimal;
            }
        }

        [Browsable(true), Category(""), Description("单击按钮时增加或减少的数量"), DefaultValue(1)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public float Increment { set; get; }

        [Browsable(true), Category(""), Description("Value的string类型")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public new string Text { get { return string.Format("{0:F" + _decimal + "}", _value); } }





        [Browsable(true), Category(""), Description("")]
        public event ValueEvent ValueChanged;


        protected override void CalcSize()
        {
            _borderRect = new Rectangle(BORDER_W / 2, BORDER_W / 2, Width - BORDER_W, Height - BORDER_W);
            _leftRect = new Rectangle(BORDER_W, BORDER_W, Common.RBUTTON_W, Height - BORDER_W - BORDER_W);
            _rightRect = new Rectangle(Width - BORDER_W - Common.RBUTTON_W, BORDER_W, Common.RBUTTON_W, _leftRect.Height);
            _leftIcon = Shape.Minus(_leftRect, 6);
            _rightIcon = Shape.Plus(_rightRect, 6);
 
            SizeF sf = CreateGraphics().MeasureString(string.Format("{0:F" + _decimal + "}", _value), Font);
            _textRect = new RectangleF(_leftRect.Right + (_rightRect.X - _leftRect.Right - sf.Width) / 2f, BORDER_W + (Height - BORDER_W - BORDER_W - sf.Height) / 2f, sf.Width, sf.Height);
        }

        /// <summary>
        /// 线程,持续增减
        /// </summary>
        private void Plus()
        {
            while (true)
            {
                if (IsDisposed) break;

                if (Environment.TickCount - _plusTime > 1000)
                {
                    try
                    {
                        Invoke(new Action(() => { PlusMinus(); }));
                    }
                    catch (Exception)
                    {
                        break;
                    }
                }

                System.Threading.Thread.Sleep(50);
            }
        }

        private void PlusMinus()
        {
            if (_leftDown)
            {
                if (_right)
                {
                    if ((int)_value == _value)
                        _value--;
                    else
                        _value = Convert.ToSingle(Math.Floor(_value));
                }
                else
                {
                    _value -= Increment;
                }
                if (_value < _min) _value = _min;
            }
            else if (_rightDown)
            {
                if (_right)
                {
                    if ((int)_value == _value)
                        _value++;
                    else
                        _value = Convert.ToSingle(Math.Ceiling(_value));
                }
                else
                {
                    _value += Increment;
                }
                if (_value > _max) _value = _max;
            }
            else
            {
                return;
            }

            CalcSize();
            Refresh();
            ValueChanged?.Invoke(this);
        }

        private void FlatNumberBox_Paint(object sender, PaintEventArgs e)
        {
            BufferedGraphicsContext current = BufferedGraphicsManager.Current;
            BufferedGraphics bg = current.Allocate(CreateGraphics(), DisplayRectangle);
            Graphics g = bg.Graphics;

            g.Clear(Common.BACK_COLOR);
            if (Inside)
            {
                if (_leftDown)
                    g.FillRectangle(Common.BLUE_BRUSH, _leftRect);
                else if (_leftOver)
                    g.FillRectangle(Common.OVER_BRUSH, _leftRect);
                if (_rightDown)
                    g.FillRectangle(Common.BLUE_BRUSH, _rightRect);
                else if (_rightOver)
                    g.FillRectangle(Common.OVER_BRUSH, _rightRect);


                g.DrawRectangle(Common.BLUE_PEN, _borderRect);
                g.DrawLine(Common.BLUE_PEN, _leftRect.Right, _leftRect.Top, _leftRect.Right, _leftRect.Bottom);
                g.DrawLine(Common.BLUE_PEN, _rightRect.X, _rightRect.Y, _rightRect.X, _rightRect.Bottom);
            }
            else
            {
                g.DrawRectangle(Common.BORDER_PEN, _borderRect);
            }

            for (int i = 0; i < _leftIcon.Length; i += 2)
                g.DrawLine(Common.FORE_PEN, _leftIcon[i], _leftIcon[i + 1]);
            for (int i = 0; i < _rightIcon.Length; i += 2)
                g.DrawLine(Common.FORE_PEN, _rightIcon[i], _rightIcon[i + 1]);
            g.DrawString(string.Format("{0:F" + _decimal + "}", _value), Font, Common.FORE_BRUSH, _textRect);

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

        private void FlatNumberBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                _right = false;
            else if (e.Button == MouseButtons.Right)
                _right = true;
            else
                return;


            _plusTime = Environment.TickCount;
            if (_leftOver) _leftDown = true;
            else if (_rightOver) _rightDown = true;
            PlusMinus();
        }

        private void FlatNumberBox_MouseMove(object sender, MouseEventArgs e)
        {
            bool b1 = _leftRect.Contains(e.Location);
            bool b2 = _rightRect.Contains(e.Location);

            if (b1 != _leftOver || b2 != _rightOver)
            {
                _leftOver = b1;
                _rightOver = b2;
                Refresh();
            }

        }

        private void FlatNumberBox_MouseUp(object sender, MouseEventArgs e)
        {
            _leftDown = false;
            _rightDown = false;
            Refresh();
        }


    }
}