当前位置:首页 > 人生 > 作品墙 > 正文内容

RadioButton 单选按钮控件调用文档

作品墙3小时前


命名空间:CConUI
继承:System.Windows.Forms.Control
可见性:public class RadioButton
默认尺寸:130 × 20
默认事件:CheckedChanged(设计器双击控件即生成该事件处理器)
定位:自绘单选按钮——左侧圆环 + 选中内部实心圆点 + 右侧文字;同一父容器内自动互斥(选中一个时自动取消其它 RadioButton)。


一、作用

一个自绘的单选按钮,具备如下特性:

  • 圆环自适应高度:圆的直径 = Height - CirclePadding × 2,控件变高圆跟着变大;

  • 选中圆点:选中时在圆环内画一个直径 ≈ 外圆 45% 的实心圆点;

  • 状态颜色:圆环边框支持三态颜色——常态 BorderColor / 悬停 HoverColor / 按下 PressedColor;

  • 自动互斥:同父容器内选中一个时,自动把其它 RadioButton 的 Checked 置为 false;

  • 文字:圆环右侧自动偏移 6px 绘制 Text,ForeColor / Font 可控,超长自动省略号(EllipsisCharacter)。

状态与视觉对照

状态圆环颜色内部圆点
常态(未选中、未悬停)BorderColor无
悬停HoverColor无
按下PressedColor无
选中按上面的悬停/按下/常态规则画一个直径 ≈ 外圆 45% 的 CheckedColor 实心圆点

二、快速上手

using System.Drawing;
using System.Windows.Forms;
using CConUI;

// 1. 创建控件
var rb = new RadioButton();

// 2. 放入容器(自动互斥发生在此父容器内)
rb.Parent = panel1;
rb.Location = new Point(20, 20);
rb.Text = "选项 A";

// 3. 初始选中
rb.Checked = true;

// 4. 订阅选中状态变化
rb.CheckedChanged += (s, e) =>
{
    var r = (RadioButton)s;
    Console.WriteLine((r.Text) + " → " + r.Checked);
};

// 5. 外观自定义(可选)
rb.BorderColor  = Color.FromArgb(139, 148, 158);
rb.HoverColor   = Color.FromArgb(173, 186, 199);
rb.PressedColor = Color.FromArgb(88, 166, 255);
rb.CheckedColor = Color.FromArgb(88, 166, 255);
rb.RingThickness = 3f;
rb.CirclePadding = 0;
rb.ForeColor = Color.White;
rb.Font = new Font("Microsoft YaHei", 9F);

三、构造函数

public RadioButton()

项目说明
参数无
作用初始化自绘单选按钮
实际行为① 启用 UserPaint | AllPaintingInWmPaint | OptimizedDoubleBuffer | ResizeRedraw 样式(自绘 + 双缓冲 + 尺寸变化自动重绘);
② 默认尺寸 Size = (130, 20);
③ 默认前景色 Color.FromArgb(238, 238, 238);
④ 默认光标 Cursors.Hand
默认尺寸130 × 20
默认状态Checked = false、RingThickness = 3f、CirclePadding = 0
var rb = new RadioButton
{
    Parent = panel1,
    Text = "选项 A"
};

四、公开属性

4.1 public bool Checked

项目说明
类型bool
默认false
CategoryCCon
DefaultValuefalse
作用控件的选中状态
副作用(赋值时值有变化)① 触发 CheckedChanging(此时 Checked 还是旧值);
② 写入新值;
③ 若新值为 true 且 Parent != null,遍历父容器内所有控件,把其它 RadioButton 的 Checked 置为 false(自动互斥);
④ 触发 CheckedChanged;
⑤ Invalidate() 重绘
幂等赋相同值直接返回,不触发任何事件、不重绘
互斥范围仅限同一 Parent.Controls。若多个 RadioButton 位于不同容器(如不同 Panel),则不会自动互斥
rb1.Checked = true;
rb2.Checked = true;   // rb1 会自动被置为 false
rb2.Checked = true;   // 已经是 true,无事发生

4.2 public int CirclePadding

项目说明
类型int(像素)
默认0
CategoryCCon
DefaultValue0
作用圆环与控件上下左右边缘之间的内边距。
0:圆直径 = Height,圆环紧贴控件上下边缘;
> 0:圆按此值向内缩,圆的直径 = Height - CirclePadding × 2
取值范围Math.Max(0, value)——自动 clamp 到 ≥0
副作用赋值后 Invalidate() 重绘
约束建议 CirclePadding < Height / 2;若过大导致直径 ≤4,绘制时兜底为 4
rb.CirclePadding = 0;   // 圆直径 = 控件高度(默认)
rb.CirclePadding = 2;   // 圆直径 = 高度 - 4
rb.CirclePadding = 4;   // 圆直径 = 高度 - 8

4.3 public float RingThickness

项目说明
类型float(像素)
默认3f
CategoryCCon
DefaultValue3f
作用圆环边框的线宽
取值范围Math.Max(0.5f, value)——自动 clamp 到 ≥0.5
副作用赋值后 Invalidate() 重绘
绘制处理绘制时 ringRect 向内缩 RingThickness / 2,避免画笔居中描边时溢出外接矩形
rb.RingThickness = 3f;
rb.RingThickness = 2f;   // 更细的圆环
rb.RingThickness = 4f;   // 更粗的圆环

4.4 颜色属性

public Color BorderColor

项目说明
类型Color
默认Color.FromArgb(139, 148, 158)(中灰)
CategoryCCon
作用圆环在常态(未悬停、未按下)下的边框颜色

public Color HoverColor

项目说明
类型Color
默认Color.FromArgb(173, 186, 199)(浅灰)
CategoryCCon
作用鼠标悬停时圆环的颜色

public Color PressedColor

项目说明
类型Color
默认Color.FromArgb(88, 166, 255)(亮蓝)
CategoryCCon
作用鼠标按下时圆环的颜色

public Color CheckedColor

项目说明
类型Color
默认Color.FromArgb(88, 166, 255)(亮蓝)
CategoryCCon
作用选中时内部实心圆点的填充色
rb.BorderColor  = Color.FromArgb(139, 148, 158);
rb.HoverColor   = Color.FromArgb(173, 186, 199);
rb.PressedColor = Color.FromArgb(88, 166, 255);
rb.CheckedColor = Color.FromArgb(88, 166, 255);

4.5 重写的外观属性

public override string Text

项目说明
类型string
CategoryCCon
作用圆环右侧显示的文字;空串时不绘制
副作用赋值后 Invalidate()
绘制起始 X = 圆右边缘 + 6px;LineAlignment = Center 垂直居中;超长自动省略号(EllipsisCharacter)

public override Color ForeColor

项目说明
类型Color
默认Color.FromArgb(238, 238, 238)(浅白)
CategoryCCon
作用文字颜色

public override Font Font

项目说明
类型Font
CategoryCCon
作用文字字体

五、公开事件

public event EventHandler CheckedChanged

项目说明
参数EventHandler:sender 为当前 RadioButton,e 为 EventArgs.Empty
CategoryCCon
默认事件是([DefaultEvent("CheckedChanged")])
触发时机Checked 值改变后;若是“被其它 RadioButton 自动置为 false”,也会触发此事件
不触发情况赋相同值不触发
触发顺序CheckedChanging → 更新 Checked → 自动互斥其它项 → CheckedChanged
rb.CheckedChanged += (s, e) =>
{
    var r = (RadioButton)s;
    Console.WriteLine(r.Text + " 状态:" + r.Checked);
};

public event EventHandler CheckedChanging

项目说明
参数EventHandler
CategoryCCon
触发时机Checked 值即将改变前——此时 Checked 仍为旧值
用途记录切换前的状态;由于 EventArgs 为空,不支持取消操作
不触发情况赋相同值不触发
bool _lastState = false;

rb.CheckedChanging += (s, e) =>
{
    _lastState = ((RadioButton)s).Checked;
};

六、公开方法

RadioButton 没有新增 public 方法。所有公开方法继承自 Control(如 Invalidate()、Focus()、BringToFront() 等)。

内部重写方法(protected override,外部不可直接调用)

方法可见性作用
OnPaint(PaintEventArgs e)protected override绘制:外圆环 → 选中圆点 → 文字
OnMouseEnter(EventArgs e)protected override设置 _isHover = true 并重绘
OnMouseLeave(EventArgs e)protected override清除悬停与按下状态并重绘
OnMouseDown(MouseEventArgs e)protected override左键按下时设置 _isPressed = true 并重绘
OnMouseUp(MouseEventArgs e)protected override左键抬起时清 _isPressed;若抬起点在客户区内 → Checked = true

七、公开成员速查表

成员来源类型说明
RadioButton()本类构造函数默认尺寸 130×20
Checked本类属性(bool)选中状态;true 时自动互斥同容器内其它 RadioButton
CirclePadding本类属性(int)圆环与控件边缘的内边距(默认 0)
RingThickness本类属性(float)圆环线宽(默认 3f,≥0.5f)
BorderColor本类属性(Color)常态圆环颜色
HoverColor本类属性(Color)悬停圆环颜色
PressedColor本类属性(Color)按下圆环颜色
CheckedColor本类属性(Color)选中内部圆点颜色
Text(重写)Control属性(string)圆环右侧文字
ForeColor(重写)Control属性(Color)文字颜色
Font(重写)Control属性(Font)文字字体
Size / ClientSizeControl属性(Size)控件尺寸;圆直径 = 高度 - CirclePadding × 2
CursorControl属性默认 Hand(手型)
CheckedChanged本类事件(默认事件)状态改变后触发
CheckedChanging本类事件状态改变前触发(Checked 仍是旧值)
Invalidate()Control方法触发重绘
OnPaint(e)本类(override)方法(protected)绘制逻辑,外部不可直接调用
OnMouseEnter / OnMouseLeave / OnMouseDown / OnMouseUp本类(override)方法(protected)鼠标交互,外部不可直接调用

八、绘制原理(深入理解)

8.1 计算圆环尺寸

float diameter = this.Height - (this._circlePadding * 2f);
if (diameter <= 4f) diameter = 4f;

float circleX = this._circlePadding;
float circleY = this._circlePadding;
RectangleF outerCircle = new RectangleF(circleX, circleY, diameter, diameter);
要点说明
diameter = Height - CirclePadding × 2上下各留 CirclePadding 像素,因此减去 × 2。
CirclePadding=0 时直径 = 控件高度,圆环紧贴上下边缘
≤ 4f 兜底控件过小或 padding 过大时,强制直径 4,避免 0 或负值导致绘制异常
circleX = circleY = CirclePadding圆心从 (CirclePadding, CirclePadding) 开始,左上角贴合

8.2 决定圆环颜色

Color ringColor;
if (this._isPressed)
    ringColor = this._pressedColor;
else if (this._isHover)
    ringColor = this._hoverColor;
else
    ringColor = this._borderColor;

优先级:按下 > 悬停 > 常态。

8.3 绘制外圆环

float halfThickness = this._ringThickness / 2f;
RectangleF ringRect = RectangleF.Inflate(outerCircle, -halfThickness, -halfThickness);

if (ringRect.Width > 0 && ringRect.Height > 0)
{
    using (var pen = new Pen(ringColor, this._ringThickness))
        g.DrawEllipse(pen, ringRect);
}
要点说明
ringRect 内缩 halfThicknessPen 居中描边时,外边缘会超出路径 RingThickness / 2。内缩半个线宽后,外边缘正好贴到 outerCircle,不会被控件裁剪
ringRect.Width ≤ 0 保护当 RingThickness ≥ 直径时,圆环退化成点,不绘制

8.4 绘制选中圆点

if (this._checked)
{
    float innerDiameter = diameter * 0.45f;
    float innerX = circleX + (diameter - innerDiameter) / 2f;
    float innerY = circleY + (diameter - innerDiameter) / 2f;
    RectangleF innerCircle = new RectangleF(innerX, innerY, innerDiameter, innerDiameter);

    using (var brush = new SolidBrush(this._checkedColor))
        g.FillEllipse(brush, innerCircle);
}
要点说明
innerDiameter = diameter × 0.45内点直径约为外圆的 45%,视觉上内外留空,看起来像是“圆环 + 实心圆点”
innerX = circleX + (diameter - innerDiameter) / 2水平居中:(diameter - innerDiameter) / 2 是左右各留的空隙
innerY 同理垂直居中

8.5 绘制文字

float textX = circleX + diameter + 6f;
RectangleF textRect = new RectangleF(textX, 0, this.Width - textX, this.Height);

using (var brush = new SolidBrush(this.ForeColor))
using (var sf = new StringFormat
{
    Alignment = StringAlignment.Near,
    LineAlignment = StringAlignment.Center,
    Trimming = StringTrimming.EllipsisCharacter
})
{
    g.DrawString(this.Text, this.Font, brush, textRect, sf);
}
要点说明
textX = circleX + diameter + 6文字起点 = 圆右边缘 + 6px 间距
LineAlignment = Center文字垂直居中于控件高度
Trimming = EllipsisCharacter文字过长时自动省略号,避免溢出
宽度计算this.Width - textX,即圆右侧到控件右边缘的剩余宽度

九、交互一览

操作效果
鼠标进入控件_isHover = true,圆环变 HoverColor
鼠标离开控件_isHover = false、_isPressed = false,圆环恢复正常或按状态
左键按下_isPressed = true,圆环变 PressedColor
左键抬起(在控件内)Checked = true(走 setter:触发事件 + 互斥 + 重绘)
左键抬起(移出控件外)不选中,仅清除 _isPressed
右键 / 中键不响应
键盘本类未重写键盘处理:Space / 方向键不会切换;如需键盘支持请自行扩展

十、完整使用示例

示例 1:三个选项互斥

using System.Drawing;
using System.Windows.Forms;
using CConUI;

var rb1 = new RadioButton { Parent = panel1, Text = "选项 A", Location = new Point(20, 20) };
var rb2 = new RadioButton { Parent = panel1, Text = "选项 B", Location = new Point(20, 50) };
var rb3 = new RadioButton { Parent = panel1, Text = "选项 C", Location = new Point(20, 80) };

rb1.Checked = true;   // 默认 A
rb2.CheckedChanged += (s, e) =>
{
    if (rb2.Checked) Console.WriteLine("选中 B");
};
rb3.CheckedChanged += (s, e) =>
{
    if (rb3.Checked) Console.WriteLine("选中 C");
};

示例 2:自定义配色(深色主题)

var rb = new RadioButton
{
    Parent = panel1,
    Text = "深色主题选项",
    Location = new Point(20, 20),
    ForeColor      = Color.White,
    BorderColor    = Color.FromArgb(90, 90, 95),
    HoverColor     = Color.FromArgb(140, 140, 150),
    PressedColor   = Color.FromArgb(0, 200, 255),
    CheckedColor   = Color.FromArgb(0, 200, 255),
    RingThickness  = 2.5f,
    CirclePadding  = 2
};

示例 3:缩小圆环(增加内边距)

var rb = new RadioButton
{
    Parent = this,
    Size = new Size(150, 24),
    Text = "缩小的圆环",
    CirclePadding = 4,   // 圆直径 = 24 - 8 = 16
    RingThickness = 2f
};

示例 4:加粗圆环

var rb = new RadioButton
{
    Parent = this,
    Size = new Size(150, 30),
    Text = "粗圆环",
    CirclePadding = 2,
    RingThickness = 4.5f,
    BorderColor = Color.Gray,
    CheckedColor = Color.Lime
};

示例 5:用事件处理做“选项确认”

var rb1 = new RadioButton { Parent = this, Text = "男", Location = new Point(20, 20) };
var rb2 = new RadioButton { Parent = this, Text = "女", Location = new Point(20, 50) };

rb1.CheckedChanged += OnGenderChanged;
rb2.CheckedChanged += OnGenderChanged;

void OnGenderChanged(object sender, EventArgs e)
{
    var r = (RadioButton)sender;
    if (!r.Checked) return;
    Console.WriteLine("当前选择:" + r.Text);
}




转载请注明出处。

本文链接:http://www.pythonopen.com/?id=20

相关文章

已经实现的一些算法

编码CConA1是一种可复原的编码算法,用于将文本或字节转换为纯字母。可用于文件名混淆,避免因包含违...

CConUI-WinForm

CConUI-WinForm

介绍CConUI-WinForm 是一款精心打造的 WinForm 控件库,它依托于.Net Fra...

横向滚动条HScrollBar 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control版本:基于所提供...

纵向滚动条VScrollBar 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control版本:基于所提供...

菜单MenuItem 与 ContextMenu 控件调用文档

命名空间:CConUI依赖:System.Windows.Forms、System.Drawing、...

图片框PictureBox 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control定位:自绘图片框...