Introduction
One big framework's handicap is the low number of visual controls. Luckily the most useful are yet present, but often we find some problem with the less common control. Some days ago I developed a program that translate the colors in the HTML code. In the beginning, I used simply three trackbar to change the red, green and blue. In a second moment I need to put a more quick and intuitive solution, so I build this ColorPicker. This control allow to select a color faster than the previous one. Because I haven't seen a similar control in this section, I decide to post it.
In the last update I added a consistent number of controls. All controls are listed below:
ColorPickers (namespace Fuliggine.ColorPickers) |
StableColorPicker |
Is a circular color picker. It allow to select a single color. |
SquareColorPicker |
Is a control that, given a base color show and allow to select it's tones. |
ColorBar |
Is a control that show and allow to select all base color derived from RGB except white and black. |
FullColorBar |
Is a control that show and allow to select all base color derived from RGB (also white and black). |
ColorViewers (namespace Fuliggine.ColorPickers) |
MonoFrameColor |
Is a control with frame that show the selected color. |
DoubleFrameColor |
Is a control with two frame that show the two selected colors. |
ColorGradient |
Is a control that show all tones of a given color; |
Special Pointers (namespace Fuliggine.ColorPickers) |
HolePointer |
Is the pointer that select the color in the controls. |
The ColorPickers Controls
The most part of these controls don't need any word, almost I think. For CodeBar and full code bar I divided the width in some section to allow all the possible combination of R,G,B. After that I found the step of color done in every pixel and draw the control line by line...
protected override void OnPaint(PaintEventArgs e)
{
int R=255;
int G=0;
int B=0;
//orizzontal...
int colorstep=255/ ( this.Width/6 );
int i=0;
//the color step x pixel
for(B=0;B<256;B+=colorstep ,i++)
{
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
}
B=255;
for(R=255;R>0;R-=colorstep,i++)
{
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
}
R=0;
for(G=0;G<256;G+=colorstep,i++)
{
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
}
G=255;
for(B=255;B>0;B-=colorstep,i++)
{
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
}
B=0;
for(R=0;R<256;R+=colorstep,i++)
{
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
}
R=255;
B=0;
for(G=255;G>0;G-=colorstep,i++)
{
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
}
}
A similar way is used also in the Color Gradient and SquareColorPicker, but there only the tones of the color are shown.
protected override void OnPaint(PaintEventArgs e)
{
int ScaleY=255/this.Height;
for ( int y = 0 ; y<this.Height;y++)
{
int r=pColor.R-(y*ScaleY);
if(r<0)
{
r=0;
}
int g=pColor.G-(y*ScaleY);
if(g<0)
{
g=0;
}
int b=pColor.B-(y*ScaleY);
if(b<0)
{
b=0;
}
e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(r,g,b)),1),0,y,this.Width,y);
}
}
The Mono and Double Fame Color are realized by simple panels. The Hole pointer is a simple control that bring itself in the apparent bounds when the mouse drag it. Basing on its position controls it is decided what's the selected color.
The Color Picker Application
The demo is that I find a nice application, nice and simple but useful for who always use the HTML language. This application show a way to use the StableColorPicker.
How to know the RGB color
I have decided to do a round rainbow. The main problem is that in a RGB system we have 3 variables and in the plain there are only two. So I decide to take the X value as Red, Y value as Green and the distance from center as Blue. The circle is inscribed in a square of 255 pixel for each side. The distance from the center is calculated with the Pitagora's Theorema and resized to fit in the range 0-255. So at every point is associated with one value between 0 and 255.
How to paint the circle
To paint the circle, I have two ways: the first one is to paint all the point on the ray for each angle; the second one is to paint every point in a circle each circle. This two different way can be selected by the user .This piece of code is shown here:
protected override void OnPaint(PaintEventArgs e)
{
//set some usefull var
int offsett= 1;
int width=this.ClientRectangle.Width-2;
int height=this.ClientRectangle.Height-2;
int rx= width/2;
int x=10;
int y=10;
int cx=offsett+rx;
double teta=0 ;
//refresh the background
e .Graphics.FillRectangle(new SolidBrush(this.BackColor),this.ClientRectangle);
//The core of painting
if ( AnimationRadial==true)
{
for ( teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
{
for ( double ray = 0 ; ray<rx ;ray= ray+1)
{
x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
y= cx - Convert.ToInt32(ray* Math.Sin(teta));
Rectangle rect= new Rectangle(x,y,1,1);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
}
}
}
else
{
for ( double ray = 0 ; ray<rx ;ray= ray+1)
{
for ( teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
{
x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
y= cx - Convert.ToInt32(ray* Math.Sin(teta));
Rectangle rect= new Rectangle(x,y,1,1);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
}
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
//set some usefull var
int offsett= 1;
int width=this.ClientRectangle.Width-2;
int height=this.ClientRectangle.Height-2;
int rx= width/2;
int x=10;
int y=10;
int cx=offsett+rx;
double teta=0 ;
//refresh the background
e .Graphics.FillRectangle(new SolidBrush(this.BackColor),this.ClientRectangle);
//The core of painting
if ( AnimationRadial==true)
{
for ( teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
{
for ( double ray = 0 ; ray<rx ;ray= ray+1)
{
x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
y= cx - Convert.ToInt32(ray* Math.Sin(teta));
Rectangle rect= new Rectangle(x,y,1,1);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
}
}
}
else
{
for ( double ray = 0 ; ray<rx ;ray= ray+1)
{
for ( teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
{
x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
y= cx - Convert.ToInt32(ray* Math.Sin(teta));
Rectangle rect= new Rectangle(x,y,1,1);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
}
}
}
}
How to select a color
To select a color I made a special class that can be moved by the user. Every Color Picker has one of this and the control return the color under it.
Problems
A big problem is the flickering repainting. I resolve taking the screenshot of this control, and putting it on a new control derived from paintbox. This isn't an elegant solution but works...I call this new control StableColorPicker.
Classes
In this release we have the first version of the control (ColorPicker) which works fine, but isn't very stable, than the second stable version(StableColorPicker).
Credits
If you would see my other work please visit my home page: http://zeppaman.altervista.org