ARGB颜色对话框 ArgbColorDialog 控件调用文档
命名空间:CConUI
类型:public static class ArgbColorDialog
定位:运行时用的 ARGB 颜色选择对话框(模态)。
内部把 ArgbColorPicker(下拉面板)包装成一个独立的 Form,通过一个内部适配器 FormEditorService 把「关闭下拉」的语义映射为「设置 DialogResult = OK 并关闭窗体」。
与属性网格编辑器的关系:
- 设计时(属性面板里点色块)使用的是ArgbColorEditor(UITypeEditor);
- 运行时(例如按钮点击后弹窗选色)使用的是ArgbColorDialog.Show(...);
- 两者最终都是复用ArgbColorPicker的 UI。
一、公开成员一览
| 成员 | 类型 | 说明 |
|---|---|---|
Show(Color? initial = null, IWin32Window owner = null) | public static 方法 | 弹出模态对话框,返回用户选择的颜色或 null |
本类只有 1 个公开方法(
Show)。内部类FormEditorService是private,外部无法访问。
二、方法签名
public static Color? Show(Color? initial = null, IWin32Window owner = null)
| 项目 | 说明 |
|---|---|
| 签名 | public static Color? Show(Color? initial = null, IWin32Window owner = null) |
| 类/方法性质 | static(无需实例化,直接 ArgbColorDialog.Show(...)) |
| 作用 | 弹出一个模态的 ARGB 颜色选择对话框,等待用户操作后返回结果 |
三、参数说明
1) Color? initial = null
| 项目 | 说明 |
|---|---|
| 类型 | System.Drawing.Color?(可空 Color) |
| 是否必填 | 否(有默认值 null) |
| 含义 | 对话框初始显示的颜色(A/R/G/B 四个输入框、Alpha 滑块、预览条都会以此初始化) |
为 null 时 | 内部兜底为 Color.Black |
| 保留 Alpha | 传入的 Alpha 会完整保留(不做强制 255) |
// 用当前颜色作为初始色 ArgbColorDialog.Show(this.BackColor); // 用半透明红色作为初始色(A=128) ArgbColorDialog.Show(Color.FromArgb(128, 255, 0, 0)); // 使用默认(黑) ArgbColorDialog.Show(null);
2) IWin32Window owner = null
| 项目 | 说明 |
|---|---|
| 类型 | System.Windows.Forms.IWin32Window |
| 是否必填 | 否(有默认值 null) |
| 含义 | 宿主窗口;通过 host.ShowDialog(owner) 传给 Form,作为模态父窗口 |
为 null 时 | 调用无参 ShowDialog(),没有父窗口 |
| 作用 | 影响焦点/激活行为(有 owner 时,owner 会被禁用,避免用户切到父窗口) |
// 推荐:在窗体内部调用时把 this 传进去 ArgbColorDialog.Show(Color.Gray, this); // 无 owner ArgbColorDialog.Show(Color.Gray);
关于弹出位置:本方法在内部把
StartPosition设成了Manual,不使用 owner 的居中,而是固定在鼠标位置右下偏移+10, +10像素处(并做屏幕工作区防溢出)。owner只影响模态/焦点行为,不影响位置。
四、返回值
| 返回情况 | 值 | 触发条件 |
|---|---|---|
| 用户确认 | Color(HasValue == true) | 用户点击对话框里的「确认」按钮,或双击色板色块 |
| 用户取消 | null(HasValue == false) | 按 Esc、点击窗体右上角关闭按钮,或其它 DialogResult != OK 情况 |
Color? picked = ArgbColorDialog.Show(Color.White, this);
if (picked.HasValue)
{
// 用户确认了一个颜色
this.BackColor = picked.Value;
}
else
{
// 用户取消,什么也不做
}五、调用方式(常用模式)
模式 1:作为属性/字段更新
using System.Drawing;
using System.Windows.Forms;
using CConUI;
private Color _themeColor = Color.FromArgb(255, 0, 120, 215);
private void btnPickThemeColor_Click(object sender, EventArgs e)
{
Color? c = ArgbColorDialog.Show(_themeColor, this);
if (c.HasValue)
{
_themeColor = c.Value;
// 应用到某个控件
panel1.BackColor = _themeColor;
// 如果目标控件属性的编辑器是 ArgbColorEditor,也可通过属性面板改
}
}模式 2:批量修改多个控件的统一颜色
private void btnPickForeColor_Click(object sender, EventArgs e)
{
Color? c = ArgbColorDialog.Show(Color.White, this);
if (!c.HasValue) return;
foreach (Control child in this.Controls)
{
if (child is Button btn) btn.ForeColor = c.Value;
}
}模式 3:配合属性网格里的属性(设计时)与运行时手动调用
// 假设有这么一个控件属性(设计时用 ArgbColorEditor 编辑)
[Editor(typeof(ArgbColorEditor), typeof(System.Drawing.Design.UITypeEditor))]
public Color AccentColor { get; set; }
// 运行时允许用户通过按钮重新选择
private void btnEditAccent_Click(object sender, EventArgs e)
{
Color? c = ArgbColorDialog.Show(myControl.AccentColor, this);
if (c.HasValue) myControl.AccentColor = c.Value;
}模式 4:半透明颜色(注意保留 Alpha)
// 用半透明颜色初始化,用户在对话框里不动 Alpha 就会保留
Color semi = Color.FromArgb(128, 0, 120, 215);
Color? c = ArgbColorDialog.Show(semi, this);
if (c.HasValue)
{
// c.Value.A 通常仍是 128(除非用户在对话框里改了 Alpha 滑块/输入框)
label1.Text = $"A={c.Value.A}, R={c.Value.R}, G={c.Value.G}, B={c.Value.B}";
}六、对话框交互一览
| 操作 | 效果 |
|---|---|
| 点击 8×8 色板某格 | 替换当前 RGB(Alpha 保持当前值),刷新预览、输入框、色板高亮框 |
| 双击色板某格 | 等价于“点击该色块 + 点击确认” → 直接返回该颜色并关闭对话框 |
| 拖动 Alpha 滑块 | 更新 Alpha 通道,刷新预览与 A 输入框 |
| 在 A / R / G / B 输入框打字 | 只允许数字;越界值自动 Clamp 到 0–255;实时刷新预览 |
| 点击「确认」按钮 | 提交当前值(SelectedColor = _current)→ FormEditorService.CloseDropDown() → 设置 DialogResult=OK → 关闭窗体 → Show 返回 picker.SelectedColor |
按 Esc | 设置 DialogResult=Cancel → 关闭 → Show 返回 null |
| 点右上角 X | 关闭 → DialogResult 为 Cancel → Show 返回 null |
七、内部实现要点(了解即可,不需要调用)
| 项目 | 说明 |
|---|---|
| 承载窗体 | 临时 Form,FormBorderStyle.FixedDialog,标题「选择颜色 (ARGB)」,不显示任务栏 |
| 内容 | 一个 ArgbColorPicker(Dock=Fill),构造参数是 startColor |
| 尺寸 | host.ClientSize = picker.Size(picker 在构造时已按布局算好自己的 ClientSize) |
| 初始位置 | Cursor.Position + (10, 10) |
| 防溢出 | 以 Screen.FromPoint(mousePos).WorkingArea 为工作区,四边越界时分别向左/上平移贴边 |
| Esc | host.KeyPreview = true + KeyDown 里判断 Keys.Escape |
| 确认后的返回 | FormEditorService.CloseDropDown() 里先设 DialogResult=OK 再 Close(),ShowDialog() 因此返回 OK |
// 伪代码,帮助理解内部时序: // 1. 用户点「确认」 // → ArgbColorPicker.BtnOk_Click // → picker.SelectedColor = 当前颜色 // → picker.EditorService.CloseDropDown() // → host.DialogResult = OK // → host.Close() // 2. Show() 里的 host.ShowDialog() 返回 DialogResult.OK // 3. Show() 返回 picker.SelectedColor // 4. using 块结束,host 被 Dispose
八、与其他类的配合对照
| 场景 | 使用类 | 调用方式 |
|---|---|---|
属性面板(设计时)里编辑 Color 属性 | ArgbColorEditor | 在属性上加 [Editor(typeof(ArgbColorEditor), typeof(UITypeEditor))] |
| 运行时弹模态对话框 | ArgbColorDialog | ArgbColorDialog.Show(初始色, owner) |
| 自定义承载(自行管理 UI) | ArgbColorPicker(internal) | 外部程序集不可用;CConUI 内部才可 new ArgbColorPicker(...) |
| 颜色预览框(带棋盘格) | ColorPreviewBox(internal) | 外部不可用 |
九、注意事项
类名为
ArgbColorDialog(已修正零宽字符问题)。若在旧版源码中看到ArgbColorDialog(中间藏有 U+200B 零宽空格),在外部引用时会编译不过——请使用本版本的正确名称。该方法是模态的(阻塞式)。调用
Show(...)后会阻塞当前 UI 线程直到对话框关闭;不要在后台线程调用。不要在 UI 线程未运行的上下文(例如控制台程序)里直接调用,
Form.ShowDialog需要消息泵。initial为null时才回退为黑色。如果传Color.Transparent,会被完整保留(Alpha=0),此时预览区会完全显示棋盘格。取消返回
null,而不是返回初始值。因此调用方需要自己判断HasValue,不要误用picked.Value。双击色板 = 选中 + 确认。想“只选不关”请单击色块。
弹出位置由内部固定为鼠标 +10,+10,不受
owner影响。如果你需要自定义位置,需要自己创建一个Form包裹ArgbColorPicker(但ArgbColorPicker是 internal,外部程序集做不到——除非使用本程序集内部的扩展方法)。不要长期持有
owner。对话框关闭后返回的颜色是值类型Color,不引用任何 UI 对象。返回值是精确的
Color(含 Alpha)。如果目标属性在设计时使用的是ArgbColorEditor,运行时用本对话框设置同一个属性,效果一致(两者底层都是ArgbColorPicker)。IWin32Window owner通常是窗体或控件,例如this(在Form内部);传null或IntPtr.Zero会导致没有父窗口,行为可能不符合用户预期(例如最小化宿主窗口时对话框不会一起最小化)。
十、完整示例
using System;
using System.Drawing;
using System.Windows.Forms;
using CConUI;
public partial class Form1 : Form
{
private Color _accentColor = Color.FromArgb(255, 0, 120, 215);
public Form1()
{
InitializeComponent();
// 初始应用到某个控件
panel1.BackColor = _accentColor;
// 点击按钮打开颜色选择对话框
btnChoose.Click += BtnChoose_Click;
}
private void BtnChoose_Click(object sender, EventArgs e)
{
Color? picked = ArgbColorDialog.Show(_accentColor, this);
if (picked.HasValue)
{
_accentColor = picked.Value;
panel1.BackColor = _accentColor;
// 半透明时同步展示 Alpha
lblInfo.Text = string.Format(
"A={0}, R={1}, G={2}, B={3}",
_accentColor.A, _accentColor.R, _accentColor.G, _accentColor.B);
}
else
{
lblInfo.Text = "已取消选择";
}
}
} 转载请注明出处。
