命名空间:CConUI
继承:System.Windows.Forms.Control
版本:基于所提供的源码
定位:全自绘纵向滚动条,支持上下箭头、滑轨、滑块、双色轨道、图片箭头、只读模式、轻性能模式、自动适应移动子控件。
一、快速上手
using CConUI;
// 1. 创建控件
VScrollBar vBar = new VScrollBar();
// 2. 放到父容器上
vBar.Parent = panel1;
vBar.Dock = DockStyle.Right; // 通常贴在右侧
vBar.Width = 30;
// 3. 设置滚动范围
vBar.Minimum = 0;
vBar.Maximum = 500;
vBar.LargeChange = 50; // 翻页步长 + 决定滑块高度
vBar.SmallChange = 10; // 箭头单步
// 4. 订阅事件
vBar.ValueChanged += (s, e) =>
{
Console.WriteLine("当前滚动值:" + vBar.Value);
};
// 5. 主动赋值
vBar.Value = 100;
二、构造函数
public VScrollBar()
| 项目 | 说明 |
|---|
| 参数 | 无 |
| 作用 | 创建纵向滚动条控件 |
| 默认尺寸 | 30 × 150 像素 |
| TabStop | true(可获得焦点、支持键盘 ↑/↓) |
| 默认值 | Minimum=0、Maximum=100、Value=0、SmallChange=1、LargeChange=10 |
用法:
VScrollBar vBar = new VScrollBar();
// 或
var vBar = new VScrollBar { Width = 24, Height = 300 };
三、事件
public event EventHandler ValueChanged
| 项目 | 说明 |
|---|
| 参数 | EventHandler,sender 为当前 VScrollBar,e 为 EventArgs.Empty |
| 触发时机 | Value 发生实际变化后 |
| 特殊情况 | ① 设为相同值不触发;② LightPerformanceMode=true 时,拖动滑块过程中不触发,松手时触发一次;③ Minimum/Maximum 调整导致 Value 被强制校正也会触发 |
| 触发顺序 | 先执行“自动适应移动子控件”,再触发该事件 |
用法:
vBar.ValueChanged += (sender, e) =>
{
int v = ((VScrollBar)sender).Value;
textBox1.Text = v.ToString();
};
四、属性
说明:
4.1 颜色类(Category:CCon_颜色)
public Color ArrowBackColor
| 项目 | 说明 |
|---|
| 类型 | System.Drawing.Color |
| 默认 | Color.FromArgb(45, 45, 48) |
| 作用 | 箭头按钮区域的背景常态色,同时是控件整体背景色(轨道与滑块会覆盖中间部分) |
vBar.ArrowBackColor = Color.FromArgb(30, 30, 30);
public Color TrackColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(28, 28, 28) |
| 作用 | 滑轨底色(滑块未覆盖处) |
public Color TrackColor2
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(0, 120, 215) |
| 作用 | 双色轨道时,滑块上方轨道的颜色(配合 UseDualColorTrack=true) |
vBar.UseDualColorTrack = true;
vBar.TrackColor2 = Color.DodgerBlue;
public Color ThumbColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(80, 80, 80) |
| 作用 | 滑块常态颜色 |
public Color ThumbHoverColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(110, 110, 110) |
| 作用 | 鼠标悬停在滑块上时显示的颜色。只读模式不生效 |
public Color ThumbDownColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(145, 145, 145) |
| 作用 | 鼠标按下滑块时显示的颜色。只读模式不生效 |
public Color ArrowColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(190, 190, 190) |
| 作用 | 内置三角箭头的颜色。仅当 DrawArrow=true 时有效 |
public Color ArrowHoverBackColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(62, 62, 66) |
| 作用 | 鼠标悬停或按下箭头按钮时,箭头区域的背景色。只读模式不生效 |
public Color BorderColor
| 项目 | 说明 |
|---|
| 类型 | Color |
| 默认 | Color.FromArgb(20, 20, 20) |
| 作用 | 边框颜色。仅当 DrawBorder=true 且 BorderSize>0 时有效 |
4.2 行为类(Category:CCon_行为)
public int Value
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 0 |
| 取值 | 由 setter 自动 Clamp 到 [Minimum, Maximum] 区间 |
| 作用 | 当前滚动条位置 |
| 副作用 | ① 若值发生变化,重绘并触发 ValueChanged;② 若 AutoAdapt=true,同步移动父控件内其他子控件 |
vBar.Value = 120; // 越界会被自动夹到 [Minimum, Maximum]
int cur = vBar.Value;
public int Minimum
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 0 |
| 作用 | 滚动范围下限 |
| 联动 | 若设置的 Minimum > Maximum,会自动把 Maximum 抬到 Minimum;随后 CoerceValue() 可能改变 Value 并触发事件 |
public int Maximum
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 100 |
| 作用 | 滚动范围上限 |
| 联动 | 若设置的 Maximum < Minimum,会自动把 Minimum 压到 Maximum;随后 CoerceValue() 可能改变 Value 并触发事件 |
vBar.Maximum = 2000;
public int SmallChange
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 1 |
| 取值 | 内部 Math.Max(1, value),至少为 1 |
| 作用 | 单击箭头(或按键盘 ↑/↓)时的单步增量;仅在 AutoAdapt=false 时作为单步量使用 |
vBar.SmallChange = 10; // 单击箭头一次,Value 变化 10
public int LargeChange
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 10 |
| 取值 | 内部 Math.Max(1, value),至少为 1 |
| 作用 | ① 单击滑轨翻页步长;② 鼠标滚轮步长;③ 决定滑块高度比例;④ 当 AutoAdapt=true 时,作为箭头/键盘的单步步长 |
| 备注 | 该值越大,滑块越高;range + LargeChange 为总内容长度的语义值 |
vBar.LargeChange = 50; // 翻页一次走 50;同时滑块更高
public bool ShowArrowArea
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | true |
| 作用 | 是否显示上下箭头区域。false 时轨道占满内容区域、箭头不显示且不响应点击 |
vBar.ShowArrowArea = false; // 隐藏箭头
public int ArrowHeight
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 16 |
| 取值 | Math.Max(0, value),负数视为 0 |
| 作用 | 上下箭头区域的高度(纵向滚动条,箭头在上下) |
vBar.ArrowHeight = 20;
public bool DrawArrow
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | true |
| 作用 | true:绘制内置三角箭头(颜色由 ArrowColor 决定);false:改用 UpArrowImage / DownArrowImage 系列图片 |
vBar.DrawArrow = false; // 改用图片箭头
public bool UseDualColorTrack
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | false |
| 作用 | 启用双色轨道:滑块上方轨道使用 TrackColor2,下方仍用 TrackColor |
vBar.UseDualColorTrack = true;
public bool ShowThumb
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | true |
| 作用 | 是否绘制滑块方块。false 时滑块不可见,但命中测试、拖动、Value 计算仍然有效 |
vBar.ShowThumb = false; // 只显示轨道,但仍可交互
public bool LightPerformanceMode
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | false |
| 作用 | 轻性能模式:拖动滑块过程中不实时触发 ValueChanged,只重绘;松开鼠标左键时触发一次 |
vBar.LightPerformanceMode = true;
public bool IsReadOnly
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | false |
| 作用 | 只读模式:滑块可见但不可拖动、不可点击箭头、不可滚轮、不可键盘操作,也不显示悬停/按下颜色;仅用于展示进度 |
| 副作用 | 开启时会立即清除所有交互状态并释放鼠标捕获 |
vBar.IsReadOnly = true;
4.3 自动适应类(Category:CCon_自动适应)
public bool AutoAdapt
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | false |
| 作用 | true:滚动时同步移动父控件下所有子控件(排除滚动条自身)的 Top,实现“内容随滚动条滚动” |
| 方向 | Value 增大 → 子控件 Top 减小(向上移动),即“向下滚动内容” |
| 联动 | 若同时 AutoAdaptAutoSetMax=true,开启时会调用 ApplyAdaptiveMax() 自动计算 Maximum |
| 备注 | 属性切换时,会把 _lastAutoAdaptValue 重置为当前 Value |
vBar.AutoAdapt = true;
vBar.AutoAdaptAutoSetMax = true;
public bool AutoAdaptAutoSetMax
| 项目 | 说明 |
|---|
| 类型 | bool |
| 默认 | false |
| 作用 | 自动适应开启时,是否把 Maximum 自动设为 GetAdaptiveMax() 的结果 |
| 触发时机 | 本属性由 false→true 且 AutoAdapt 已为 true 时立即计算;AutoAdapt 由 false→true 且本属性已为 true 时立即计算;其它情况不主动改 Maximum |
public int AdaptiveMax(只读)
| 项目 | 说明 |
|---|
| 类型 | int |
| 作用 | 返回当前 GetAdaptiveMax() 的计算结果 |
| 说明 | 在属性窗口隐藏、不参与设计器序列化 |
int max = vBar.AdaptiveMax;
4.4 图片类(Category:CCon_图片)
仅在 DrawArrow=false 时使用;图片会被按比例缩放并居中放入箭头区域;优先级:按下 > 悬停 > 常态。
public Image UpArrowImage
public Image UpArrowHoverImage
public Image UpArrowDownImage
| 项目 | 说明 |
|---|
| 类型 | System.Drawing.Image |
| 作用 | 上箭头的常态 / 悬停 / 按下图片 |
public Image DownArrowImage
public Image DownArrowHoverImage
public Image DownArrowDownImage
| 项目 | 说明 |
|---|
| 类型 | Image |
| 作用 | 下箭头的常态 / 悬停 / 按下图片 |
vBar.DrawArrow = false;
vBar.UpArrowImage = Image.FromFile("up_normal.png");
vBar.UpArrowHoverImage = Image.FromFile("up_hover.png");
vBar.UpArrowDownImage = Image.FromFile("up_down.png");
vBar.DownArrowImage = Image.FromFile("down_normal.png");
vBar.DownArrowHoverImage = Image.FromFile("down_hover.png");
vBar.DownArrowDownImage = Image.FromFile("down_down.png");4.5 边框类(Category:CCon_边框)
public bool DrawBorder
public int BorderSize
| 项目 | 说明 |
|---|
| 类型 | int |
| 默认 | 1 |
| 取值 | Math.Max(0, value) |
| 作用 | 边框粗细(像素)。0 视为不绘制 |
vBar.DrawBorder = true;
vBar.BorderSize = 1;
vBar.BorderColor = Color.FromArgb(40, 40, 40);
4.6 被隐藏的继承属性
以下 Control 属性在属性窗口、智能感知、设计器序列化中被隐藏(不可用或无语义),但代码里仍可读写:
Text、ForeColor、Font、BackColor、BackgroundImage、BackgroundImageLayout。
如需背景色,请使用 ArrowBackColor、TrackColor 等专用颜色属性。
五、公开方法
public int GetAdaptiveMax()
| 项目 | 说明 |
|---|
| 签名 | public int GetAdaptiveMax() |
| 参数 | 无 |
| 返回值 | int |
| 作用 | 计算自动适应所需的最大滚动距离:max(子控件.Top + 子控件.Height) - Parent.ClientSize.Height;如小于 0 则返回 0;若 Parent 为 null 或没有其它子控件则返回 0 |
| 用途 | ① 当 AutoAdaptAutoSetMax=true 时被自动调用;② 可外部调用,用于手动设置 Maximum |
// 手动方式
vBar.Maximum = vBar.GetAdaptiveMax();
注意事项:该方法是基于子控件的当前位置计算的。当 AutoAdapt 已经滚动过内容(子控件已被移动)之后,返回值会变小。如果你的业务需要基于“初始位置”计算,请在初始化时调用,或记录原始位置后在必要时手动复位子控件位置再调用。
六、完整示例
示例 1:基础纵向滚动条
VScrollBar vBar = new VScrollBar
{
Parent = panel1,
Dock = DockStyle.Right,
Width = 30,
Minimum = 0,
Maximum = 1000,
SmallChange = 10,
LargeChange = 100,
Value = 0
};
vBar.ValueChanged += (s, e) =>
{
Console.WriteLine("Value = " + vBar.Value);
};示例 2:双色 + 图片箭头
VScrollBar vBar = new VScrollBar
{
Parent = panel1,
Dock = DockStyle.Right,
UseDualColorTrack = true,
TrackColor2 = Color.DodgerBlue,
DrawArrow = false,
ArrowHeight = 22,
UpArrowImage = Image.FromFile("up.png"),
DownArrowImage = Image.FromFile("down.png")
};示例 3:自动适应纵向滚动
// 假设 panel1 内含多个控件,超出可视高度
VScrollBar vBar = new VScrollBar
{
Parent = panel1,
Dock = DockStyle.Right,
Width = 20,
AutoAdapt = true,
AutoAdaptAutoSetMax = true, // 自动设置 Maximum = panel1 下最低子控件 Bottom - panel1.ClientSize.Height
LargeChange = 50
};
vBar.ValueChanged += (s, e) => { /* 业务处理 */ };提示:面板 Panel.AutoScroll 与本控件“自动适应”不建议混用,因为两者都会修改子控件位置,可能产生冲突。
示例 4:只读进度展示
VScrollBar progress = new VScrollBar
{
Parent = panel1,
Dock = DockStyle.Right,
IsReadOnly = true, // 不可拖动
ShowArrowArea = false,
ShowThumb = true,
UseDualColorTrack = true,
TrackColor2 = Color.Green,
Minimum = 0,
Maximum = 100
};
progress.Value = 42; // 代码里仍可修改 Value,界面会刷新示例 5:轻性能模式
VScrollBar vBar = new VScrollBar
{
Parent = panel1,
Dock = DockStyle.Right,
LightPerformanceMode = true // 拖动过程中不触发事件,松手触发一次
};
vBar.ValueChanged += (s, e) =>
{
RebuildLargeContent(vBar.Value);
};
七、交互一览
| 操作 | 触发结果 |
|---|
| 单击上箭头 / 下箭头 | Value ∓/= CurrentSmallStep |
| 按住箭头不动 | 400ms 后每 60ms 重复一次 |
| 单击滑块上方轨道 | Value -= LargeChange |
| 单击滑块下方轨道 | Value += LargeChange |
| 右键单击轨道 | 滑块中心跳到点击位置 |
| 按住滑块拖动 | 实时更新(或轻性能下松手更新) |
| 滚轮 | Value ∓= steps * LargeChange(Delta>0 向上滚动,Value 减小) |
| 键盘 ↑ / ↓ | Value ∓/= CurrentSmallStep |
AutoAdapt=true 时 | CurrentSmallStep = LargeChange |
八、注意事项汇总
Value 会自动 Clamp,不要依赖越界值。
Minimum / Maximum 互相联动,设置其中一个可能修改另一个。
自动适应的 Maximum 是快照,内容变化后需调用 GetAdaptiveMax() 重新设置 Maximum = GetAdaptiveMax()。
AdaptiveMax 与 GetAdaptiveMax() 等价,但仅前者是只读属性。
AutoAdapt 与 Panel.AutoScroll 不建议同时使用。
Text/Font/BackColor 等被隐藏,不要尝试修改它们来改变外观,使用专用颜色属性。
ValueChanged 在轻性能模式下只是延迟,不是丢弃。
九、HScrollBar 与 VScrollBar 差异对照表
| 项目 | HScrollBar | VScrollBar |
|---|
| 方向 | 横向 | 纵向 |
| 默认尺寸 | 150 × 30 | 30 × 150 |
| 箭头位置 | 左右 | 上下 |
ArrowHeight 语义 | 左右箭头宽度 | 上下箭头高度 |
| 双色轨道区域 | 滑块左侧 | 滑块上方 |
| 键盘 | ← / → | ↑ / ↓ |
| 滚轮 Delta>0 方向 | Value 减小(向左滚) | Value 减小(向上滚) |
| 自动适应移动的子控件属性 | Left | Top |
Value 增大时子控件移动方向 | 向左(Left -= delta) | 向上(Top -= delta) |
GetAdaptiveMax 计算依据 | max(Left + Width) - Parent.ClientSize.Width | max(Top + Height) - Parent.ClientSize.Height |
UpArrowImage 系列实际语义 | 左箭头图片 | 上箭头图片 |
DownArrowImage 系列实际语义 | 右箭头图片 | 下箭头图片 |