Gradient Color Picker V2 revises the earlier implementation by revising the user interface and eliminating a need to determine the color of a pixel at a specific screen location.
Table of Contents
The symbol returns the reader to the top of the Table of Contents.
Introduction
This article revises an earlier implementation of the Gradient Color Picker [^]. The incentive for the revision were reader comments regarding the earlier implementation.
The only areas of change were in the positioning of the user interface components and the implementation of the gradient_PAN and the button_PAN panels. The original article should be referenced for details.
Implementation
gradient_PAN
When either the start or end color is chosen, the fill_gradient_PAN method is invoked.
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 );
}
This method insures that both the start and end colors have been chosen. If so, the method executes the following:
gradient_PAN.Visible = true;
gradient_PAN.Invalidate ( );
The gradient_PAN has the PAN_OnPaint event handler attached.
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 );
}
The PAN_OnPaint event hander is very simple. All it does is create a LinearGradientBrush [^] and uses it to fill the gradient_PAN client rectangle.
In this revision the left side of the gradient_PAN is aligned horizontally with the horizontal center of the start_color_BUT and the right side of the gradient_PAN is aligned horizontally with the horizontal center of the end_color_BUT. The number of colors label and the numeric up/down control have been moved to midway between the start- and end-color buttons.
button_PAN
When the Generate button is clicked, the balance of the tool's GUI is rendered. In most cases this entails making various objects visible. However, generating the button_PAN panel is somewhat more complex.
bool fill_button_PAN ( )
{
int right_most = 0;
int spacing = 0;
int top = 2;
colors.Clear ( );
colors = get_linear_gradient_colors ( start_color,
end_color,
number_of_colors );
foreach ( Control control in button_PAN.Controls )
{
if ( control is Button )
{
control.Click -= new EventHandler (
gradient_BUT_Click );
}
}
button_PAN.Controls.Clear ( );
buttons.Clear ( );
spacing = ( button_PAN.Size.Width -
( BUTTON_WIDTH * number_of_colors ) ) /
( number_of_colors - 1 );
for ( int i = 0; ( i < number_of_colors ); i++ )
{
Button button = new Button ( );
int left = ( i * ( spacing + BUTTON_WIDTH ) );
button.FlatStyle = FlatStyle.Popup;
button.Location = new Point ( left, top );
button.Size = BUTTON_SIZE;
button.Click += new EventHandler (
gradient_BUT_Click );
right_most = button.Location.X + button.Size.Width;
button.BackColor = colors [ i ];
button.UseVisualStyleBackColor = false;
buttons.Add ( button );
}
if ( right_most < ( button_PAN.Size.Width - EPSILON ) )
{
int pixels = 1;
int start = 0;
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;
}
}
for ( int i = 0; ( i < buttons.Count ); i++ )
{
Button button = buttons [ i ];
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 );
}
The major change in fill_button_PAN is the elimination of the dependency on the contents of the gradient_PAN to determine the background color of the buttons in the button_PAN. To achieve this, the get_linear_gradient_colors method is invoked to fill a list of colors whose members will be assigned to each button as its background color.
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 );
}
The method MinMax was introduced to avoid repeating the same logic over and over again.
int MinMax ( float start,
float difference,
float i )
{
int result = ( int ) ( start - ( i * difference ) + 0.5F );
return ( Math.Max ( 0, Math.Min ( 255, result ) ) );
}
In this revision, the colors list and get_linear_gradient_colors replace generate_back_color.
Acknowlegments
The authors of the readers comments are:
- steve-redTrans
- BillWoodruff
I thank both for their comments that caused this article to be written.
References
Conclusion
This article has revised a tool that provides developers with the ability to pick colors from a linear color gradient.
Development Environment
The Gradient Color Picker was developed in the following environment:
Microsoft Windows 7 Professional SP 1 |
Microsoft Visual Studio 2008 Professional SP1 |
Microsoft Visual C# 2008 |
Microsoft .Net Framework Version 3.5 SP1 |
History
05/05/2020 | Original article |
05/28/2021 | Revised article |