编辑
2025-10-14
C#
00

目录

完整代码实现
增加动画过渡与Enabled = false效果
注意事项

在WinForm开发中,默认的CheckBox控件外观比较单调。通过继承CheckBox类并重写OnPaint方法,我们可以使用GDI+绘制出更加美观的自定义CheckBox控件。

完整代码实现

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AppControls { public class 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; } } }

image.png

增加动画过渡与Enabled = false效果

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AppControls { public class 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; private float currentAnimationValue = 0f; private bool isAnimating = false; private CheckState previousState; private Color fromColor; private Color toColor; private const int ANIMATION_DURATION = 200; // 动画持续时间(毫秒) private const int TIMER_INTERVAL = 16; // 约60fps private float 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); } } }

image.png

注意事项

这个自定义CheckBox控件实现了一个现代化的外观,通过GDI+的绘制功能,我们可以完全控制控件的视觉效果。你可以根据需要修改颜色、大小等参数来适应不同的应用场景。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!