FlatCheck.cs 7.0 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.Theme
{
    /// <summary>
    /// 复选框控件
    /// </summary>
    [DefaultProperty("Checked")]
    [DefaultEvent("CheckedChanged")]
    public partial class FlatCheck : FlatBase
    {
        private bool _check;
        private GraphicsPath _switchPath = new GraphicsPath();
        private PointF _switchPoint = new PointF();
        private RectangleF _textRect = new RectangleF();
        private TextSwitchRelation _relation;
        
        private int _radius;
        private int _between;

        /// <summary>
        /// 复选框控件
        /// </summary>
        public FlatCheck()
        {
            InitializeComponent();
            _relation = TextSwitchRelation.SwitchBeforeText;
            _radius = 9;
            _between = 20;
            Text = "";
        }

        /// <summary>
        /// 显示的文本
        /// </summary>
        [Browsable(true), Category(""), Description("显示的文本,用英文逗号分隔可以切换开/关的文本"), DefaultValue("")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get => base.Text;
            set
            {
                base.Text = value;
                CalcSize();
                Refresh();
            }
        }

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

        /// <summary>
        /// 组件是否处于选中状态
        /// </summary>
        [Browsable(true), Category(""), Description("组件是否处于选中状态"), DefaultValue(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public bool Checked
        {
            set
            {
                _check = value;
                CalcSize();
                Refresh();
                CheckedChanged?.Invoke(this);
            }
            get
            {
                return _check;
            }
        }

        /// <summary>
        /// 左右半圆的半径
        /// </summary>
        [Browsable(true), Category(""), Description("左右半圆的半径"), DefaultValue(9)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Radius
        {
            get
            {
                return _radius;
            }
            set
            {
                _radius = value;
                CalcSize();
                Refresh();
            }
        }

        /// <summary>
        /// 左右半圆的圆心距离
        /// </summary>
        [Browsable(true), Category(""), Description("左右半圆的圆心距离"), DefaultValue(20)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int CircleSpace
        {
            set
            {
                _between = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _between;
            }
        }

        /// <summary>
        /// 文本开关位置
        /// </summary>
        [Browsable(true), Category(""), Description("指定文本与开关的相对位置"), DefaultValue(TextSwitchRelation.SwitchBeforeText)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public TextSwitchRelation TextSwitchRelation
        {
            set
            {
                _relation = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _relation;
            }
        }

        /// <summary>
        /// Check属性更改时发生
        /// </summary>
        [Browsable(true), Category(""), Description("Check属性更改时发生")]
        public event Event.ValueChanged CheckedChanged;



        /// <summary>
        /// 计算大小
        /// </summary>
        protected override void CalcSize()
        {
            int diameter = _radius * 2;  //直径
            RectangleF rect1 = new RectangleF(6, (Height - diameter) / 2f, diameter, diameter);
            RectangleF rect2 = new RectangleF(6 + _between, (Height - diameter) / 2f, diameter, diameter);
            SizeF sf = CreateGraphics().MeasureString(Text, Font);
            _textRect = new RectangleF(rect2.X + rect2.Width + 6, (Height - sf.Height) / 2f, sf.Width, sf.Height);

            _switchPath = new GraphicsPath();
            _switchPath.AddArc(rect1, 90, 180);
            _switchPath.AddLine(rect1.X + _radius, rect1.Y, rect2.X + _radius, rect2.Y);
            _switchPath.AddArc(rect2, -90, 180);
            _switchPath.AddLine(rect2.X + _radius, rect2.Y + diameter, rect1.X + _radius, rect1.Y + diameter);

            if (Checked)
            {
                _switchPoint.X = rect2.X + _radius;
                _switchPoint.Y = rect2.Y + _radius;
            }
            else
            {
                _switchPoint.X = rect1.X + _radius;
                _switchPoint.Y = rect1.Y + _radius;
            }
        }

        private void FlatCheck_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

            e.Graphics.Clear(Common.BACK_COLOR);
            if (Checked)
            {
                e.Graphics.FillPath(Common.BLUE_BRUSH, _switchPath);
                e.Graphics.DrawPath(Common.BLUE_PEN, _switchPath);
            }
            else if (Inside)
                e.Graphics.DrawPath(Common.BLUE_PEN, _switchPath);
            else
                e.Graphics.DrawPath(Common.BORDER_PEN, _switchPath);

            int r = _radius * 2 - 6;
            e.Graphics.FillEllipse(Common.FORE_BRUSH, _switchPoint.X - r / 2f, _switchPoint.Y - r / 2f, r, r);

            string s;
            string[] arr = Text.Split(',');
            if (arr.Length == 2)
            {
                if (Checked)
                    s = arr[1];
                else
                    s = arr[0];
            }
            else
            {
                s = Text;
            }
            e.Graphics.DrawString(s, Font, new SolidBrush(Common.FORE_COLOR), _textRect);
        }

        private void FlatCheck_MouseDown(object sender, MouseEventArgs e)
        {
            Checked = !Checked;
        }


    }
}