在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 编辑过