Reader Level:
ARTICLE

Fuliggine ColorPickers

Posted by zeppaman Articles | GDI+ & Graphics May 11, 2006
In this article the author shows to build color picker and embedded color controls using GDI+.
  • 0
  • 0
  • 9167

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.

Sample Image - ColorPicker.jpg

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

COMMENT USING

Trending up