创建颜色选择控件






4.08/5 (8投票s)
2004年12月15日
5分钟阅读

86148

454
创建一个用户控件,用于从颜色映射中选择前景色和背景色。
引言
在做一个简单的图标编辑器时,我遇到了颜色选择的问题。当然,我可以使用颜色选择对话框,但因为它是一个对话框,所以用户无法直接使用。
看看常见的图形应用程序(例如,Paint Shop Pro),图像的编辑画布通常伴随着一个显示颜色映射的控件。然后,用户只需在控件上单击鼠标左键或右键,即可设置活动的前景色和背景色。
下面的代码演示了如何使用 .NET 框架的 alpha 混合功能轻松创建这样的控件。
创建控件
在实际创建控件之前,让我们先总结一下控件的功能:
- 显示所有可用颜色的映射图
- 通过在颜色映射图的任何位置单击鼠标左键来设置前景色属性
- 通过在颜色映射图的任何位置单击鼠标右键来设置背景色属性
由于我们希望保持简单,该控件首先创建一个与控件画布大小相同的颜色映射位图。然后在 Paint 事件中,控件简单地将位图绘制到服务上。
由于画布大小和位图大小相同,画布的每个像素都对应于位图中的一个像素。选择颜色现在变成了一个查找单击坐标处的像素颜色(在 MouseUp
事件处理程序中完成)的问题。
颜色映射
最困难的部分是创建颜色映射位图,因为我们实际上是从三维空间映射到二维空间。呃……什么……你完全没听懂???
让我来解释一下。每种颜色都由三个值组成:红色 (R)、绿色 (G) 和蓝色 (B),也称为 RGB。对于 24 位颜色,每个值 R、G 或 B 的范围可以是 0..255(如果你还没弄明白,0..255 的范围恰好是 8 位,并且我们有 8 位的红色、8 位的绿色和 8 位的蓝色,总共就是 24 位颜色)。每种颜色都可以看作是具有轴:红色、绿色和蓝色三维空间中的一个坐标。所有颜色共同构成了 RGB 空间中大小为 255 的一个立方体。正是这个立方体,我们想要将其展平到一个二维画布上。
让我们快速计算一下:假设我们想显示所有颜色。使用 24 位,我们有 256*256*256 种颜色。现在如果你想在宽度为 256 像素的画布上显示这些颜色,那么长度将变为 256*256 = 65536 像素。我不了解你的显示器尺寸,但我认为公平地说,你的显示器无法支持 65536 像素的长度。此外,拉伸控件的宽度在这里也不起作用。所以显示所有颜色是不可能的。
所以问题归结为:如何显示颜色,使得用户可以选择所有类型的颜色,但不能选择所有颜色。
幸运的是,我们不必重新发明轮子。只需看看其他程序(例如,Paint Shop Pro),它们是如何解决这个问题的。基本上,它们会在黑白主背景上显示一组固定的六种基本颜色,这些颜色以重叠的圆圈显示,并且像光一样相互作用,也就是说,如果你混合红色和黄色,就会变成橙色。
创建六种基本颜色很简单。其中三种很容易找到:红色、绿色、蓝色(也称为三原色)。另外三种是混合色,可以通过两种三原色组合而成。
- 红 + 绿 = 黄
- 绿 + 蓝 = 青
- 蓝 + 红 = 品红
以 RGB 值表示,三原色是:
- 红 = (255, 0, 0)
- 绿 = (0, 255, 0)
- 蓝 = (0, 0, 255)
混合色是:
- 黄 = (255, 255, 0)
- 青 = (0, 255, 255)
- 品红 = (255, 0, 255)
使用 LinearGradientBrush
可以创建黑白背景。下面是创建投影表面的代码示例。
lbrush = new LinearGradientBrush (ClientRectangle,
Color.FromArgb (255, 0, 0, 0), Color.FromArgb (255, 255, 255, 255), 0f);
g.FillRectangle (lbrush, ClientRectangle);
使用 PathGradientBrush
可以创建从基本颜色渐变为黑色的圆形。将 CenterColor
设置为基本颜色,将 SurroundColors
设置为黑色。
为了让圆形在黑白背景上像光一样作用,我们需要 alpha 通道。通过 alpha 通道,绘制到表面的颜色会与表面上现有的颜色混合。要启用 alpha 通道,请在绘制任何内容之前将 Graphics
实例 g
的 CompositingMode
设置为 SourceOver
!
g.CompositingMode = CompositingMode.SourceOver;
另外,请确保绘制时指定的每种颜色都是带有 alpha 分量(也称为 ARGB 值)的 RGB 值。幸运的是,Color
类包含一个 static
方法 FromArgb
。使用四个参数调用它,第一个参数是 alpha 值,其余参数是红色、绿色和蓝色值。下面是用代码示例绘制黄色圆。请注意指定的 alpha 值。
path = new GraphicsPath ();
path.StartFigure ();
path.AddEllipse (rect);
path.CloseFigure ();
pbrush = new PathGradientBrush (path);
pbrush.CenterColor = Color.FromArgb (255, 255, 0, 0);
pbrush.SurroundColors = new Color[] { Color.FromArgb (0, 0, 0, 0) };
g.FillEllipse (pbrush, rect);
上面的代码重复了六次,每次指定不同的基本颜色和不同的位置。
关注点
颜色映射控件可以方便快捷地选择颜色。但是,在映射图中找到相同的颜色两次是很困难的。为此,显示调色板的控件更合适。缺点是:由颜色网格绘制的调色板定义上可选择的颜色更少。历史
- 2004-12-15 - 初始发布。
- 2004-12-29 - 更新
ForeColor
和BackColor
属性现在会触发相关的颜色更改事件。