在WinForm开发中,默认的CheckBox控件外观比较单调。通过继承CheckBox类并重写OnPaint方法,我们可以使用GDI+绘制出更加美观的自定义CheckBox控件。
完整代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppControls
{
    publicclass ModernCheckBox : CheckBox
    {
        // 定义三种状态的颜色  
        private Color checkedColor = Color.MediumSlateBlue;
        private Color unCheckedColor = Color.Gray;
        private Color indeterminateColor = Color.RosyBrown;
        #region 属性  
        // 选中状态颜色  
        public Color CheckedColor
        {
            get => checkedColor;
            set
            {
                checkedColor = value;
                Invalidate();
            }
        }
        // 未选中状态颜色  
        public Color UnCheckedColor
        {
            get => unCheckedColor;
            set
            {
                unCheckedColor = value;
                Invalidate();
            }
        }
        // 不确定状态颜色  
        public Color IndeterminateColor
        {
            get => indeterminateColor;
            set
            {
                indeterminateColor = value;
                Invalidate();
            }
        }
        #endregion
        public ModernCheckBox()
        {
            // 设置控件最小高度  
            MinimumSize = new Size(0, 21);
            // 启用三态选择  
            this.ThreeState = true;
        }
        protected override void OnPaint(PaintEventArgs pevent)
        {
            // 获取绘图上下文  
            Graphics graphics = pevent.Graphics;
            // 设置抗锯齿模式  
            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            // 定义复选框的尺寸参数  
            float borderSize = 18F;        // 外边框大小  
            float checkSize = 12F;         // 选中标记大小  
            float indeterminateHeight = 2F; // 不确定状态线条高度  
            // 创建外边框矩形  
            RectangleF borderRect = new RectangleF()
            {
                X = 0.5F,
                Y = (Height - borderSize) / 2,    // 垂直居中  
                Width = borderSize,
                Height = borderSize
            };
            // 创建选中标记矩形  
            RectangleF checkRect = new RectangleF()
            {
                X = borderRect.X + ((borderRect.Width - checkSize) / 2),
                Y = (Height - checkSize) / 2,
                Width = checkSize,
                Height = checkSize
            };
            // 创建不确定状态矩形  
            RectangleF indeterminateRect = new RectangleF()
            {
                X = borderRect.X + 4,
                Y = (Height - indeterminateHeight) / 2,
                Width = borderSize - 8,
                Height = indeterminateHeight
            };
            // 使用using语句确保资源正确释放  
            using (Pen borderPen = new Pen(checkedColor, 1.6F))
            using (SolidBrush checkBrush = new SolidBrush(checkedColor))
            using (SolidBrush indeterminateBrush = new SolidBrush(indeterminateColor))
            using (SolidBrush textBrush = new SolidBrush(ForeColor))
            {
                // 清除背景  
                graphics.Clear(BackColor);
                // 根据CheckState绘制不同状态  
                switch (CheckState)
                {
                    case CheckState.Checked:
                        // 绘制选中状态  
                        graphics.DrawRectangle(borderPen,
                            borderRect.X, borderRect.Y,
                            borderRect.Width, borderRect.Height);
                        graphics.FillRectangle(checkBrush, checkRect);
                        break;
                    case CheckState.Indeterminate:
                        // 绘制不确定状态  
                        borderPen.Color = indeterminateColor;
                        graphics.DrawRectangle(borderPen,
                            borderRect.X, borderRect.Y,
                            borderRect.Width, borderRect.Height);
                        graphics.FillRectangle(indeterminateBrush, indeterminateRect);
                        break;
                    case CheckState.Unchecked:
                        // 绘制未选中状态  
                        borderPen.Color = unCheckedColor;
                        graphics.DrawRectangle(borderPen,
                            borderRect.X, borderRect.Y,
                            borderRect.Width, borderRect.Height);
                        break;
                }
                // 绘制文本  
                graphics.DrawString(Text, Font, textBrush,
                    borderSize + 8,    // 文本位置X坐标  
                    (Height - TextRenderer.MeasureText(Text, Font).Height) / 2    // 文本垂直居中  
                );
            }
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            // 根据文本自动调整控件宽度  
            Width = TextRenderer.MeasureText(Text, Font).Width + 30;
        }
        // 添加鼠标悬停效果  
        protected override void OnMouseEnter(EventArgs eventargs)
        {
            base.OnMouseEnter(eventargs);
            this.Cursor = Cursors.Hand;
        }
        protected override void OnMouseLeave(EventArgs eventargs)
        {
            base.OnMouseLeave(eventargs);
            this.Cursor = Cursors.Default;
        }
    }
}
 
增加动画过渡与Enabled = false效果
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppControls
{
    publicclass ModernCheckBox : CheckBox
    {
        // 定义三种状态的颜色  
        private Color checkedColor = Color.MediumSlateBlue;
        private Color unCheckedColor = Color.Gray;
        private Color indeterminateColor = Color.RosyBrown;
        private Color disabledColor = Color.LightGray;        // 禁用状态颜色  
        private Color disabledTextColor = Color.DarkGray;     // 禁用状态文本颜色  
        // 动画相关字段  
        private System.Windows.Forms.Timer animationTimer;
        privatefloat currentAnimationValue = 0f;
        privatebool isAnimating = false;
        private CheckState previousState;
        private Color fromColor;
        private Color toColor;
        privateconstint ANIMATION_DURATION = 200; // 动画持续时间(毫秒)  
        privateconstint TIMER_INTERVAL = 16; // 约60fps  
        privatefloat animationStep;
        #region 属性  
        // 选中状态颜色  
        public Color CheckedColor
        {
            get => checkedColor;
            set
            {
                checkedColor = value;
                Invalidate();
            }
        }
        // 未选中状态颜色  
        public Color UnCheckedColor
        {
            get => unCheckedColor;
            set
            {
                unCheckedColor = value;
                Invalidate();
            }
        }
        // 不确定状态颜色  
        public Color IndeterminateColor
        {
            get => indeterminateColor;
            set
            {
                indeterminateColor = value;
                Invalidate();
            }
        }
        // 禁用状态颜色属性  
        public Color DisabledColor
        {
            get => disabledColor;
            set
            {
                disabledColor = value;
                Invalidate();
            }
        }
        // 禁用状态文本颜色属性  
        public Color DisabledTextColor
        {
            get => disabledTextColor;
            set
            {
                disabledTextColor = value;
                Invalidate();
            }
        }
        #endregion
        public ModernCheckBox()
        {
            MinimumSize = new Size(0, 21);
            this.ThreeState = true;
            // 初始化动画计时器  
            animationTimer = new System.Windows.Forms.Timer();
            animationTimer.Interval = TIMER_INTERVAL;
            animationTimer.Tick += AnimationTimer_Tick;
            // 计算每次动画步进值  
            animationStep = 1f / (ANIMATION_DURATION / TIMER_INTERVAL);
            previousState = CheckState;
        }
        private void AnimationTimer_Tick(object sender, EventArgs e)
        {
            if (isAnimating)
            {
                currentAnimationValue += animationStep;
                if (currentAnimationValue >= 1f)
                {
                    currentAnimationValue = 1f;
                    isAnimating = false;
                    animationTimer.Stop();
                }
                Invalidate();
            }
        }
        protected override void OnCheckStateChanged(EventArgs e)
        {
            // 开始新的动画  
            StartNewAnimation();
            base.OnCheckStateChanged(e);
        }
        private void StartNewAnimation()
        {
            // 设置起始颜色  
            fromColor = GetCurrentStateColor(previousState);
            // 设置目标颜色  
            toColor = GetCurrentStateColor(CheckState);
            // 重置动画参数  
            currentAnimationValue = 0f;
            isAnimating = true;
            // 启动动画计时器  
            animationTimer.Start();
            // 更新前一个状态  
            previousState = CheckState;
        }
        private Color GetCurrentStateColor(CheckState state)
        {
            if (!Enabled) return disabledColor;
            switch (state)
            {
                case CheckState.Checked:
                    return checkedColor;
                case CheckState.Indeterminate:
                    return indeterminateColor;
                default:
                    return unCheckedColor;
            }
        }
        protected override void OnPaint(PaintEventArgs pevent)
        {
            Graphics graphics = pevent.Graphics;
            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            float borderSize = 18F;
            float checkSize = 12F;
            float indeterminateHeight = 2F;
            // 创建外边框矩形  
            RectangleF borderRect = new RectangleF()
            {
                X = 0.5F,
                Y = (Height - borderSize) / 2,
                Width = borderSize,
                Height = borderSize
            };
            // 创建选中标记矩形,添加动画缩放效果  
            float animatedCheckSize = isAnimating ?
                checkSize * currentAnimationValue :
                (CheckState == CheckState.Checked ? checkSize : 0);
            RectangleF checkRect = new RectangleF()
            {
                X = borderRect.X + ((borderRect.Width - animatedCheckSize) / 2),
                Y = (Height - animatedCheckSize) / 2,
                Width = animatedCheckSize,
                Height = animatedCheckSize
            };
            // 创建不确定状态矩形  
            RectangleF indeterminateRect = new RectangleF()
            {
                X = borderRect.X + 4,
                Y = (Height - indeterminateHeight) / 2,
                Width = borderSize - 8,
                Height = indeterminateHeight
            };
            // 计算当前动画颜色  
            Color currentBorderColor;
            Color currentFillColor;
            Color currentTextColor = Enabled ? ForeColor : disabledTextColor;
            if (isAnimating)
            {
                // 在动画过程中对颜色进行插值  
                currentBorderColor = InterpolateColor(fromColor, toColor, currentAnimationValue);
                currentFillColor = currentBorderColor;
            }
            else
            {
                currentBorderColor = GetCurrentStateColor(CheckState);
                currentFillColor = currentBorderColor;
            }
            using (Pen borderPen = new Pen(currentBorderColor, 1.6F))
            using (SolidBrush fillBrush = new SolidBrush(currentFillColor))
            using (SolidBrush textBrush = new SolidBrush(currentTextColor))
            {
                graphics.Clear(BackColor);
                // 绘制边框  
                graphics.DrawRectangle(borderPen,
                    borderRect.X, borderRect.Y,
                    borderRect.Width, borderRect.Height);
                // 根据状态绘制内部  
                switch (CheckState)
                {
                    case CheckState.Checked:
                        if (animatedCheckSize > 0)
                            graphics.FillRectangle(fillBrush, checkRect);
                        break;
                    case CheckState.Indeterminate:
                        graphics.FillRectangle(fillBrush, indeterminateRect);
                        break;
                }
                // 绘制文本  
                if (!Enabled)
                {
                    textBrush.Color = Color.FromArgb(128, disabledTextColor);
                }
                graphics.DrawString(Text, Font, textBrush,
                    borderSize + 8,
                    (Height - TextRenderer.MeasureText(Text, Font).Height) / 2
                );
            }
        }
        // 颜色插值方法  
        private Color InterpolateColor(Color from, Color to, float progress)
        {
            int r = (int)(from.R + (to.R - from.R) * progress);
            int g = (int)(from.G + (to.G - from.G) * progress);
            int b = (int)(from.B + (to.B - from.B) * progress);
            int a = (int)(from.A + (to.A - from.A) * progress);
            return Color.FromArgb(a, r, g, b);
        }
        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);
            Invalidate(); // 重绘控件  
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            // 根据文本自动调整控件宽度  
            Width = TextRenderer.MeasureText(Text, Font).Width + 30;
        }
        // 添加鼠标悬停效果  
        protected override void OnMouseEnter(EventArgs eventargs)
        {
            base.OnMouseEnter(eventargs);
            if (Enabled) // 仅在启用状态下改变光标  
            {
                Cursor = Cursors.Hand;
            }
        }
        protected override void OnMouseLeave(EventArgs eventargs)
        {
            base.OnMouseLeave(eventargs);
            this.Cursor = Cursors.Default;
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                animationTimer?.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

注意事项
这个自定义CheckBox控件实现了一个现代化的外观,通过GDI+的绘制功能,我们可以完全控制控件的视觉效果。你可以根据需要修改颜色、大小等参数来适应不同的应用场景。
阅读原文:原文链接
该文章在 2025/3/31 11:25:11 编辑过