C#winform实现像触摸屏按钮那样的开关

触摸屏的按钮开发起来非常方便,只要设置好样式和文本,以及绑定的变量,一个开关就做好了。

而用winform要实现同样的功能,要编写许多代码。

花木兰控件库的ToggleButton可以这样做切换,但是有几点不方便的地方。于是修改了以下几点:

  1. 文本修改成可以换行:
    C#winform实现像触摸屏按钮那样的开关_第1张图片
    文本居中且可以自动换行,而且通过修改Padding可以设置每一行显示多少个字,比如我要改成每行最多三个字:
    C#winform实现像触摸屏按钮那样的开关_第2张图片
  2. 圆角修改成可以设置
    C#winform实现像触摸屏按钮那样的开关_第3张图片
  3. 点击时切换文本
    在这里插入图片描述
    C#winform实现像触摸屏按钮那样的开关_第4张图片
    C#winform实现像触摸屏按钮那样的开关_第5张图片
    最终效果就是点击切换状态、背景和文本。
    查看按钮的状态。
private void toggleButton1_Click(object sender, EventArgs e)
{
    HML.ToggleButton btn = (HML.ToggleButton)sender;
    MessageBox.Show(btn.Checked.ToString());
}

控件库源码:添加链接描述
打开解决方案把 HML 项目里面的 ToggleButton 的代码替换成下面的代码,把HML项目重新生成,获得 HML.ComplexityPropertys.dll 和 HML.dll 文件,引入自己的项目即可。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace HML
{
    /// 
    /// 开关按钮控件
    /// 
    [Description("开关按钮控件")]
    [ToolboxItem(true)]
    [DefaultProperty("Checked")]
    [DefaultEvent("Click")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [ToolboxBitmap(typeof(ToggleButton), "Controls.ToggleButton.ToggleButton.bmp")]
    public class ToggleButton : MainThreadAnimationControl
    {
        #region 新增事件

        private static readonly object EventCheckedChanged = new object();
        /// 
        /// 开关状态更改事件
        /// 
        [Description("开关状态更改事件")]
        public event EventHandler CheckedChanged
        {
            add { Events.AddHandler(EventCheckedChanged, value); }
            remove { Events.RemoveHandler(EventCheckedChanged, value); }
        }

        #endregion

        #region 停用事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler RightToLeftChanged
        {
            add { base.RightToLeftChanged += value; }
            remove { base.RightToLeftChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged
        {
            add { base.ImeModeChanged += value; }
            remove { base.ImeModeChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackColorChanged
        {
            add { base.BackColorChanged += value; }
            remove { base.BackColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ForeColorChanged
        {
            add { base.ForeColorChanged += value; }
            remove { base.ForeColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageChanged
        {
            add { base.BackgroundImageChanged += value; }
            remove { base.BackgroundImageChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageLayoutChanged
        {
            add { base.BackgroundImageLayoutChanged += value; }
            remove { base.BackgroundImageLayoutChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick
        {
            add { base.DoubleClick += value; }
            remove { base.DoubleClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseDoubleClick
        {
            add { base.MouseDoubleClick += value; }
            remove { base.MouseDoubleClick -= value; }
        }

        #endregion

        #region 新增属性
        private string textChecked="中转爪已闭合";
        /// 
        /// 图标Size
        /// 
        [Description("按钮Checked文本")]
        [Category("杂项")]
        [DefaultValue(typeof(string), "中转爪已闭合")]
        public string TextChecked
        {
            get { return textChecked; }
            set { textChecked = value; Invalidate(); }
        }
        private string textUnChecked = "中转爪已打开";
        /// 
        /// 图标Size
        /// 
        [Description("按钮UnChecked文本")]
        [Category("杂项")]
        [DefaultValue(typeof(string), "中转爪已打开")]
        public string TextUnChecked
        {
            get { return textUnChecked; }
            set { textUnChecked = value; Invalidate(); }
        }
        private int cornerRadius = 10;
        /// 
        /// 图标Size
        /// 
        [Description("按钮圆角角度")]
        [Category("杂项")]
        [DefaultValue(typeof(int), "10")]
        public int CornerRadius
        {
            get { return cornerRadius; }
            set { cornerRadius = value; Invalidate(); }
        }

        private float paddingLR = 30;
        /// 
        /// 图标Size
        /// 
        [Description("按钮左右内边距")]
        [Category("杂项")]
        [DefaultValue(typeof(float), "30")]
        public float PaddingLR
        {
            get { return paddingLR; }
            set
            {
                paddingLR = value;
                this.Invalidate();
            }
        }
        private Color activateColor = Color.White;
        /// 
        /// 控件激活的虚线框颜色
        /// 
        [Description("控件激活的虚线框颜色")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DefaultValue(typeof(Color), "White")]
        public Color ActivateColor
        {
            get { return this.activateColor; }
            set
            {
                if (this.activateColor == value)
                    return;

                this.activateColor = value;
                this.Invalidate();
            }
        }

        private bool roundEnabled = true;
        /// 
        /// 是否启用圆角
        /// 
        [Description("是否启用圆角")]
        [Category("杂项")]
        [PropertyOrder(-198)]
        [DefaultValue(true)]
        public bool RoundEnabled
        {
            get { return this.roundEnabled; }
            set
            {
                if (this.roundEnabled == value)
                    return;

                this.roundEnabled = value;
                this.SetControlShape();
                this.Invalidate();
            }
        }

        private bool autoCheck = true;
        /// 
        /// 单击时是否自动更改控件状态
        /// 
        [Description("单击时是否自动更改控件状态")]
        [Category("杂项")]
        [PropertyOrder(-197)]
        [DefaultValue(true)]
        public bool AutoCheck
        {
            get { return this.autoCheck; }
            set
            {
                if (this.autoCheck == value)
                    return;

                this.autoCheck = value;
            }
        }

        private bool _Checked = false;
        /// 
        /// 开关状态
        /// 
        [Description("开关状态")]
        [Category("杂项")]
        [PropertyOrder(-196)]
        [DefaultValue(false)]
        public bool Checked
        {
            get { return this._Checked; }
            set
            {
                if (this._Checked == value)
                    return;

                this._Checked = value;
                this.Invalidate();

                if (!this.DesignMode)
                {
                    this.OnCheckedChanged(new EventArgs());
                }
            }
        }

        private Color backUnCheckedColor = Color.FromArgb(33, 90, 106);
        /// 
        /// 背景颜色(未选中、正常)
        /// 
        [Description("背景颜色(未选中、正常)")]
        [Category("杂项")]
        [PropertyOrder(-193)]
        [DefaultValue(typeof(Color), "33,90,106")]
        public Color BackUnCheckedColor
        {
            get { return this.backUnCheckedColor; }
            set
            {
                if (this.backUnCheckedColor == value)
                    return;

                this.backUnCheckedColor = value;
                this.Invalidate();
            }
        }

        private Color textUnCheckedColor = Color.White;
        /// 
        /// 文本颜色(未选中、正常)
        /// 
        [Description("文本颜色(未选中、正常)")]
        [Category("杂项")]
        [PropertyOrder(-192)]
        [DefaultValue(typeof(Color), "White")]
        public Color TextUnCheckedColor
        {
            get { return this.textUnCheckedColor; }
            set
            {
                if (this.textUnCheckedColor == value)
                    return;

                this.textUnCheckedColor = value;
                this.Invalidate();
            }
        }

        private Color backCheckedColor = Color.FromArgb(157, 222, 237);
        /// 
        /// 背景颜色(已选中、正常)
        /// 
        [Description("背景颜色(已选中、正常)")]
        [Category("杂项")]
        [PropertyOrder(-188)]
        [DefaultValue(typeof(Color), "157,222,237")]
        public Color BackCheckedColor
        {
            get { return this.backCheckedColor; }
            set
            {
                if (this.backCheckedColor == value)
                    return;

                this.backCheckedColor = value;
                this.Invalidate();
            }
        }

        private Color textCheckedColor = Color.Black;
        /// 
        /// 文本颜色(已选中、正常)
        /// 
        [Description("文本颜色(已选中、正常)")]
        [Category("杂项")]
        [PropertyOrder(-187)]
        [DefaultValue(typeof(Color), "White")]
        public Color TextCheckedColor
        {
            get { return this.textCheckedColor; }
            set
            {
                if (this.textCheckedColor == value)
                    return;

                this.textCheckedColor = value;
                this.Invalidate();
            }
        }

        private Color clickColor = Color.FromArgb(106, 100, 98);
        /// 
        /// 背景颜色(未选中、正常)
        /// 
        [Description("点击颜色")]
        [Category("杂项")]
        [PropertyOrder(-193)]
        [DefaultValue(typeof(Color), "106,100,98")]
        public Color ClickColor
        {
            get { return this.clickColor; }
            set
            {
                if (this.clickColor == value)
                    return;
                this.clickColor = value;
                this.Invalidate();
            }
        }
        #endregion

        #region 重写属性

        protected override Padding DefaultPadding
        {
            get { return new Padding(3, 3, 3, 3); }
        }

        protected override Size DefaultSize
        {
            get { return new Size(90, 24); }
        }

        //public override string Text
        //{
        //    get { return base.Text; }
        //    set
        //    {
        //        base.Text = value;
        //        this.Invalidate();
        //    }

        //}

        protected override ImeMode DefaultImeMode
        {
            get { return ImeMode.Disable; }
        }

        #endregion

        #region 停用属性
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode
        {
            get { return base.ImeMode; }
            set { base.ImeMode = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override RightToLeft RightToLeft
        {
            get { return base.RightToLeft; }
            set { base.RightToLeft = value; }
        }

        [DefaultValue(typeof(Color), "Transparent")]
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Color BackColor
        {
            get { return base.BackColor; }
            set { base.BackColor = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color ForeColor
        {
            get { return base.ForeColor; }
            set { base.ForeColor = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new ImageLayout BackgroundImageLayout
        {
            get { return base.BackgroundImageLayout; }
            set { base.BackgroundImageLayout = value; }
        }

        #endregion

        #region 字段

        /// 
        /// 鼠标按下类型
        /// 
        private MouseButtons mousedowntype = MouseButtons.None;
        /// 
        /// 鼠标已进入对象
        /// 
        private object mouseenterobject = null;

        /// 
        /// 鼠标单击动画是否进行中
        /// 
        private bool animationing = false;
        /// 
        /// 鼠标单击动画动画总时间
        /// 
        private double animationAllTime = 250;
        /// 
        /// 鼠标单击动画已使用时间
        /// 
        private double animationUsedTime = 0;
        /// 
        /// 鼠标单击动画圆心坐标
        /// 
        private Point animationpoint = Point.Empty;

        #endregion
        StringFormat stringFormat = new StringFormat();
        public ToggleButton()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.StandardClick, false);//自定义单击事件逻辑
            SetStyle(ControlStyles.StandardDoubleClick, false);//停用双加事件

            this.SuspendLayout();
            this.BackColor = Color.Transparent;
            this.SetControlShape();
            this.ResumeLayout();

            stringFormat.Alignment = StringAlignment.Center;
            stringFormat.LineAlignment = StringAlignment.Center;
        }

        #region 重写

        protected override void OnScaleDpiChangedInitialize()
        {
            this.Invalidate();
        }
        GraphicsPath graphicsPath = new GraphicsPath();
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;  //图片柔顺模式选择
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;//高质量
            g.CompositingQuality = CompositingQuality.HighQuality;//再加一点

            graphicsPath.Reset();

            graphicsPath.AddArc(GetCornerRect1(), 270, 90);
            var points = GetLine1();
            graphicsPath.AddLine(points.Item1, points.Item2);

            graphicsPath.AddArc(GetCornerRect2(), 0, 90);
            points = GetLine2();
            graphicsPath.AddLine(points.Item1, points.Item2);

            graphicsPath.AddArc(GetCornerRect3(), 90, 90);
            points = GetLine3();
            graphicsPath.AddLine(points.Item1, points.Item2);

            graphicsPath.AddArc(GetCornerRect4(), 180, 90);
            points = GetLine4();
            graphicsPath.AddLine(points.Item1, points.Item2);
            if (_Checked == false)
            {
                g.FillPath(new SolidBrush(backUnCheckedColor), graphicsPath);
            }
            else
            {
                g.FillPath(new SolidBrush(backCheckedColor), graphicsPath);
            }

            //SolidBrush back_sb = new SolidBrush(Color.Brown);
            //if (this.animationing)//点击动画
            //{
            //    g.SmoothingMode = SmoothingMode.AntiAlias;
            //    //int animationRadius = (int)Math.Ceiling(ControlHelper.AdjustRectangleMaxRadiusForPoint(this.ClientRectangle, this.animationpoint) * this.animationUsedTime / this.animationAllTime * 10 / 8);
            //    int animationRadius = 20;
            //    back_sb.Color = ControlHelper.ConvertToAnimationColor(clickColor);
            //    g.FillEllipse(back_sb, new RectangleF(this.animationpoint.X - animationRadius, this.animationpoint.Y - animationRadius, animationRadius * 2, animationRadius * 2));
            //    g.SmoothingMode = SmoothingMode.Default;
            //}
            // 文本
            g.SmoothingMode = SmoothingMode.Default;
            SolidBrush text_sb;
            if (_Checked == false){
                text_sb = new SolidBrush(textUnCheckedColor);
            }
            else
            {
                text_sb = new SolidBrush(textCheckedColor);
            }
            if (_Checked == false)
            {
                g.DrawString(TextUnChecked, this.Font, text_sb, new RectangleF(paddingLR, 2, Width - paddingLR * 2, Height), stringFormat);
            }
            else
            {
                g.DrawString(TextChecked, this.Font, text_sb, new RectangleF(paddingLR, 2, Width - paddingLR * 2, Height), stringFormat);
            }
            text_sb.Dispose();
            

            //控件激活状态虚线框
            if (this.Focused && this.ShowFocusCues)
            {
                Pen activated_border_pen = new Pen(this.ActivateColor) { DashStyle = DashStyle.Dot, Alignment = PenAlignment.Center };
                Rectangle activated_border_rect = new Rectangle(this.ClientRectangle.X + 3, this.ClientRectangle.Y + 3, this.ClientRectangle.Width - 7, this.ClientRectangle.Height - 7);
                g.DrawRectangle(activated_border_pen, activated_border_rect);
                activated_border_pen.Dispose();
            }
        }
        /// 
        /// 右上角弧线
        /// 
        /// 
        private Rectangle GetCornerRect1()
        {
            return new Rectangle(Width - cornerRadius - 1, 1, cornerRadius, cornerRadius);
        }
        /// 
        /// 右边线段
        /// 
        /// 
        private Tuple<Point, Point> GetLine1()
        {
            return new Tuple<Point, Point>(new Point(Width - 1, cornerRadius / 2),
                new Point(Width - 1, Height - cornerRadius / 2));
        }
        /// 
        /// 右下角弧线
        /// 
        /// 
        private Rectangle GetCornerRect2()
        {
            return new Rectangle(Width - cornerRadius - 1, Height - cornerRadius - 1, cornerRadius, cornerRadius);
        }
        /// 
        /// 下边线段
        /// 
        /// 
        private Tuple<Point, Point> GetLine2()
        {
            return new Tuple<Point, Point>(new Point(cornerRadius / 2 + 1, Height - 1),
                new Point(Width - cornerRadius / 2 - 1, Height - 1));
        }
        /// 
        /// 左下角弧线
        /// 
        /// 
        private Rectangle GetCornerRect3()
        {
            return new Rectangle(1, Height - cornerRadius - 1, cornerRadius, cornerRadius);
        }
        /// 
        /// 左边线段
        /// 
        /// 
        private Tuple<Point, Point> GetLine3()
        {
            return new Tuple<Point, Point>(new Point(1, Height - cornerRadius / 2 - 1),
                new Point(1, cornerRadius / 2 + 1));
        }
        /// 
        /// 左上角弧线
        /// 
        /// 
        private Rectangle GetCornerRect4()
        {
            return new Rectangle(1, 1, cornerRadius, cornerRadius);
        }
        /// 
        /// 上边线段
        /// 
        /// 
        private Tuple<Point, Point> GetLine4()
        {
            return new Tuple<Point, Point>(
                new Point(cornerRadius / 2 + 1, 1), new Point(Width - cornerRadius / 2 - 1, 1));
        }
        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);

            this.Invalidate();
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);

            this.mousedowntype = MouseButtons.None;
            this.Invalidate();
        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);

            if (!this.Enabled)
            {
                this.mousedowntype = MouseButtons.None;
                this.mouseenterobject = null;
                this.Invalidate();
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);

            if (!this.Visible)
            {
                this.mousedowntype = MouseButtons.None;
                this.mouseenterobject = null;
                this.Invalidate();
            }
        }

        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);

            if (this.Parent == null)
            {
                this.mousedowntype = MouseButtons.None;
                this.mouseenterobject = null;
                this.Invalidate();
            }
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);

            this.mouseenterobject = this;
            this.Invalidate();
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);

            this.mouseenterobject = null;
            this.Invalidate();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (!this.Focused)
            {
                this.Focus();
            }

            this.mousedowntype |= e.Button;

            if (e.Button == MouseButtons.Left)
            {
                this.animationing = true;
                this.animationUsedTime = 0;
                this.animationpoint = e.Location;
                MainThreadAnimationControl.AnimationStart(this);
                this.Invalidate();
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (this.mousedowntype.HasFlag(MouseButtons.Left) && this.ClientRectangle.Contains(e.Location))
                {
                    this.OnClick(e);
                    this.OnMouseClick(e);
                    if (this.AutoCheck)
                    {
                        this.Checked = !this.Checked;
                    }
                }
            }
            this.mousedowntype &= ~e.Button;

            base.OnMouseUp(e);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Space:
                    {
                        this.animationing = true;
                        this.animationUsedTime = 0;
                        this.animationpoint = new Point(this.ClientRectangle.X + this.ClientRectangle.Width / 2, this.ClientRectangle.Y + this.ClientRectangle.Height / 2);
                        MainThreadAnimationControl.AnimationStart(this);
                        this.Invalidate();
                        break;
                    }
            }

            base.OnKeyDown(e);
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            switch (e.KeyData)
            {
                case Keys.Space:
                    {
                        this.OnClick(EventArgs.Empty);
                        break;
                    }
            }

            base.OnKeyUp(e);
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            this.SetControlShape();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                MainThreadAnimationControl.AnimationStop(this);
            }
            base.Dispose(disposing);
        }

        /// 
        /// 动画控件动画中要处理的内容(不能时耗时操作)
        /// 
        /// 动画定时器间隔时间
        protected override void Animationing(int interval)
        {
            bool finish = false;
            this.animationUsedTime += interval;
            if (this.animationUsedTime > this.animationAllTime)
            {
                this.animationUsedTime = this.animationAllTime;
                MainThreadAnimationControl.AnimationStop(this);
                finish = true;
            }

            if (finish)
            {
                this.animationing = false;
                this.animationUsedTime = 0;
                this.animationpoint = Point.Empty;
            }

            this.Invalidate();
        }

        #endregion

        #region 虚方法

        protected virtual void OnCheckedChanged(EventArgs e)
        {
            EventHandler handler = Events[EventCheckedChanged] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region 私有方法

        /// 
        /// 设置控件形状
        /// 
        private void SetControlShape()
        {
            GraphicsPath gp = new GraphicsPath();
            if (this.RoundEnabled)
            {
                gp = ControlHelper.AdjustRectangleShapePath(this.ClientRectangle);
            }
            else
            {
                gp.AddRectangle(this.ClientRectangle);
            }

            this.Region = new Region(gp);
            gp.Dispose();
        }

        /// 
        /// ImageList更改后刷新控件
        /// 
        /// 
        /// 
        private void RecreateImageListHandler(object sender, EventArgs e)
        {
            if (this.IsHandleCreated)
            {
                this.Invalidate();
            }
        }

        /// 
        /// ImageList释放时解绑清除清除引用
        /// 
        /// 
        /// 
        private void DetachImageListHandler(object sender, EventArgs e)
        {
        }

        #endregion
    }

}

你可能感兴趣的:(C#上位机,c#,开发语言)