渐变颜色选择器 V2






3.57/5 (4投票s)
修订了早期版本的渐变颜色选择器。
目录
引言
本文是对早期 渐变色拾取器 实现的修订 [^]。修订的动力来自于读者对早期实现的评论。
更改的唯一区域是用户界面组件的定位以及 gradient_PAN 和 button_PAN 面板的实现。有关详细信息,请参考原始文章。
实现
gradient_PAN
当选择起始颜色或结束颜色时,将调用 fill_gradient_PAN 方法。
// ***************************************** fill_gradient_PAN
bool fill_gradient_PAN ( )
{
if ( have_end_color && have_start_color )
{
gradient_PAN.Visible = true;
gradient_PAN.Invalidate ( );
number_of_colors_LAB.Visible = true;
number_of_colors_NUD.Value = number_of_colors;
number_of_colors_NUD.Visible = true;
generate_BUT.Visible = true;
}
return ( true );
} // fill_gradient_PAN
此方法确保已选择起始颜色和结束颜色。如果是,则该方法执行以下操作
gradient_PAN.Visible = true;
gradient_PAN.Invalidate ( );
gradient_PAN 已附加 PAN_OnPaint 事件处理程序。
// *********************************************** PAN_OnPaint
void PAN_OnPaint ( object sender,
PaintEventArgs e )
{
base.OnPaint ( e );
e.Graphics.FillRectangle (
new LinearGradientBrush (
gradient_PAN.ClientRectangle,
start_color,
end_color,
0.0F ),
gradient_PAN.ClientRectangle );
} // PAN_OnPaint
PAN_OnPaint 事件处理程序非常简单。它所做的就是创建一个 LinearGradientBrush [^] 并使用它来填充 gradient_PAN 客户端矩形。
在此修订版中,gradient_PAN 的左侧与 start_color_BUT 的水平中心对齐,gradient_PAN 的右侧与 end_color_BUT 的水平中心对齐。颜色数量标签和数字上下控件已移至起始颜色按钮和结束颜色按钮的中间。
button_PAN
当单击 生成 按钮时,将渲染工具 GUI 的其余部分。在大多数情况下,这需要使各种对象可见。但是,生成 button_PAN 面板要复杂一些。
// ******************************************* fill_button_PAN
bool fill_button_PAN ( )
{
int right_most = 0;
int spacing = 0;
int top = 2;
// empty and regenerate the
// colors list
colors.Clear ( );
colors = get_linear_gradient_colors ( start_color,
end_color,
number_of_colors );
// remove existing event
// handlers from buttons in
// the button_PAN
foreach ( Control control in button_PAN.Controls )
{
if ( control is Button )
{
control.Click -= new EventHandler (
gradient_BUT_Click );
}
}
// remove any existing buttons
// from the button_PAN
button_PAN.Controls.Clear ( );
// clear the buttons list
buttons.Clear ( );
// compute initial spacing
// between buttons
spacing = ( button_PAN.Size.Width -
( BUTTON_WIDTH * number_of_colors ) ) /
( number_of_colors - 1 );
// create gradient buttons and
// add them to buttons list
for ( int i = 0; ( i < number_of_colors ); i++ )
{
Button button = new Button ( );
int left = ( i * ( spacing + BUTTON_WIDTH ) );
// want no borders
button.FlatStyle = FlatStyle.Popup;
button.Location = new Point ( left, top );
button.Size = BUTTON_SIZE;
button.Click += new EventHandler (
gradient_BUT_Click );
// save the position of the
// right side of the button
right_most = button.Location.X + button.Size.Width;
button.BackColor = colors [ i ];
button.UseVisualStyleBackColor = false;
buttons.Add ( button );
}
// the spacing may not be
// large enough to cause the
// buttons to completely fill
// the button panel; here we
// correct the inter-button
// spacing; EPSILON is
// currently 3
if ( right_most < ( button_PAN.Size.Width - EPSILON ) )
{
int pixels = 1;
int start = 0;
// start is expected to be
// greater than zero
start = buttons.Count -
( button_PAN.Size.Width - right_most );
for ( int i = start; ( i < buttons.Count ); i++ )
{
Point location = buttons [ i ].Location;
location.X += pixels++;
buttons [ i ].Location = location;
}
}
// copy the button from the
// buttons List to the
// button_PAN
for ( int i = 0; ( i < buttons.Count ); i++ )
{
Button button = buttons [ i ];
// place button in button_PAN
button_PAN.Controls.Add ( button );
}
button_PAN.Visible = true;
reset_BUT.Visible = true;
copy_format_GB.Visible = true;
ascending_PB.Visible = true;
copy_left_to_right_BUT.Visible = true;
descending_PB.Visible = true;
copy_right_to_left_BUT.Visible = true;
return ( true );
} // fill_button_PAN
fill_button_PAN 的主要变化是消除了对 gradient_PAN 内容的依赖来确定 button_PAN 中按钮的背景颜色。为了实现这一点,将调用 get_linear_gradient_colors 方法来填充一个颜色列表,该列表的成员将被分配给每个按钮作为其背景颜色。
// ******************************** get_linear_gradient_colors
// See https://codeproject.org.cn/Articles/5267129/
// Gradient-Color-Picker Bill Woodward comment modified
List < Color > get_linear_gradient_colors (
Color start_color,
Color end_color,
int number_of_colors )
{
List < Color > list = new List < Color > ( 0 );
float count = ( float ) number_of_colors - 1.0F;
float start_R = ( float ) start_color.R;
float difference_R = ( start_R -
( float ) end_color.R ) /
count;
float start_G = ( float ) start_color.G;
float difference_G = ( start_G -
( float ) end_color.G ) /
count;
float start_B = ( float ) start_color.B;
float difference_B = ( start_B -
( float ) end_color.B ) /
count;
for ( int i = 0; ( i < number_of_colors ); i++ )
{
int B = MinMax ( start_B, difference_B, ( float ) i );
int G = MinMax ( start_G, difference_G, ( float ) i );
int R = MinMax ( start_R, difference_R, ( float ) i );
list.Add ( Color.FromArgb ( R, G, B ) );
}
return ( list );
} // get_linear_gradient_colors
引入 MinMax 方法是为了避免一遍又一遍地重复相同的逻辑。
// **************************************************** MinMax
int MinMax ( float start,
float difference,
float i )
{
int result = ( int ) ( start - ( i * difference ) + 0.5F );
return ( Math.Max ( 0, Math.Min ( 255, result ) ) );
} // MinMax
在此修订版中,colors 列表和 get_linear_gradient_colors 取代了 generate_back_color。
致谢
读者评论的作者是
- steve-redTrans
- BillWoodruff
我感谢他们提出的评论,这些评论促成了这篇文章的撰写。
参考文献
- LinearGradientBrush [^]
- 维基百科 [^]
结论
本文修订了一个工具,该工具能够让开发人员从线性颜色渐变中拾取颜色。
开发环境
渐变色拾取器是在以下环境中开发的
Microsoft Windows 7 专业版 SP 1 |
Microsoft Visual Studio 2008 专业版 SP1 |
Microsoft Visual C# 2008 |
Microsoft .Net Framework Version 3.5 SP1 |
历史
05/05/2020 | 原文 |
05/28/2021 | 修订版文章 |