Click here to Skip to main content
15,881,898 members
Articles / Desktop Programming / Windows Forms

The Known Colors Palette Tool

Rate me:
Please Sign up or sign in to vote.
4.37/5 (9 votes)
1 Dec 2010CPOL6 min read 45K   1.1K   12   9
Presents a tool that assists in choosing colors from the known colors
Known Colors Palette

Introduction

Colors are the breath of the Internet. This article discusses some color palettes and then describes a tool that may be used to choose appropriate colors for a web page.

Background

Color History

In the early history of computing, color was not an important attribute of a successful application. Most computer terminals had a green or amber display. Furthermore, most terminals were text oriented, displaying a fixed number of characters per row and a fixed number of rows per screen. In large part, most of the applications that ran on computer terminals were command line interpreters, text editors, and modem control applications. Although there were graphical terminals available, they were very expensive and used only in specialized environments.

In 1973, the Xerox Palo Alto Research Center (PARC) developed the personal workstation, the forerunner of the modern personal computer. In 1975, PARC introduced the Graphical User Interface, with its familiar desktop and icons. To support these Parc developed bit-mapped graphics.

In 1981, with the introduction of the personal computer, IBM also introduced the Computer Graphics Adapter (CGA), sixteen colors became available to the application developer.

CGA Color Palette

In 1984, IBM introduced the Enhanced Graphics Adapter (EGA) with 64 colors.

EGA Color Palette

Then, in 1987, IBM introduced the Video Graphics Array (VGA). The VGA palette provided 256 colors.

Default VGA Palette

With the introduction of X windows, a palette, known as the X11 color names became available. The most important distinction between the X11 color names and the earlier color palettes was the ability to choose a color by specifying either its name or its RGB triplet.

Finally, with the introduction of .NET Framework 1.1, the Known Colors Palette was formalized by Microsoft. Although this palette includes some colors used by Microsoft to display various system entities (e.g., ActiveBorder, AppWorkspace, Control Dark, etc.), during the enumeration of the known colors, we can exclude these Microsoft system colors.

Need

While testing the Color Hit Testing User Control, I required a test image. I decided that a display of the US Time Zones would suffice. Because I was preparing the article for viewing on the Internet, I decided to color the image with the known colors.

I was using Microsoft Paint to create the image. During the image preparation, I stumbled across a couple of limitations in that tool's Colors?Edit Colors... dialog:

  • The colors that are displayed are not the known colors.
  • The colors that are initially displayed are not the known colors.
  • The dialog does not display a color name when the mouse hovers over the color.

To solve these two problems, I built the Known Colors Palette Tool. The requirements levied against the tool included:

  • The colors that are displayed are to be the known colors.
  • When the mouse hovers over a color swatch, the color name is to be displayed.
  • The colors may be sorted either by known color name or by the known colors' ARGB values.
  • When the mouse clicks on a color swatch, the ARGB value of the known color shall be displayed along with the individual ARGB component values.
  • A context menu shall be provided that allows the user to perform the sorts, keep the tool on top, and allow the appropriate color information to be copied to the Clipboard.

Known Colors Palette Tool

The Known Colors Palette Tool is based upon the KnownColor Enumeration that is provided by Microsoft as part of the System.Drawing assembly. Microsoft's enumeration, with the exception of the system colors, is equivalent to the CSS color names. During the enumeration of the Microsoft known color names, those known colors that are Microsoft system colors are excluded.

C#
// ************************** get_known_colors_from_Microsoft

// http://www.dreamincode.net/code/snippet1405.htm

private List < Color > get_known_colors_from_Microsoft ( )
    {
    List < Color >  colors = new List<Color> ( );
    string [ ]      color_names =
                        Enum.GetNames ( typeof (
                                            KnownColor ) );

    foreach ( string color_name in color_names )
        {
        KnownColor known_color = ( KnownColor ) Enum.Parse (
                                     typeof ( KnownColor ),
                                     color_name );

        if ( ( known_color > KnownColor.Transparent ) &&
             ( known_color < KnownColor.ButtonFace ) )
            {
            colors.Add ( Color.FromName ( color_name ) );
            }
        }

    return ( colors );
    }

The first task, after the colors are enumerated, is to create two panels, one to display the colors by name, the other to display the colors by ARGB. Both panels are created and then hidden. I create two separate panels to improve performance when switching between the two displays.

C#
// ****************************** create_colors_by_name_panel

private void create_colors_by_name_panel ( )
    {
    NameComparer  nc = new NameComparer ( );

    known_colors.Sort ( nc );
    colors_by_name_panel = populate_panel ( );
    this.Controls.Add ( colors_by_name_panel );
    colors_by_name_panel.Visible = false;
    }

// ****************************** create_colors_by_ARGB_panel

private void create_colors_by_ARGB_panel ( )
    {
    ARGBComparer  ac = new ARGBComparer ( );

    known_colors.Sort ( ac );
    colors_by_ARGB_panel = populate_panel ( );
    this.Controls.Add ( colors_by_ARGB_panel );
    colors_by_ARGB_panel.Visible = false;
    }

Two classes, NameComparer and ARGBComparer, were implemented to perform the comparisons.

C#
// ******************************************* class NameComparer

public class NameComparer : IComparer < Color >
    {

    // ************************************************** Compare

    public int Compare ( Color color_1,
                         Color color_2 )
        {

        if ( color_1 == null )
            {
            if ( color_2 == null )
                {
                                    // If color_1 is null and
                                    // color_2 is null, they're
                                    // equal
                return ( 0 );
                }
            else
                {
                                    // If color_1 is null and
                                    // color_2 is not null,
                                    // color_2 is greater.
                return ( -1 );
                }
            }
        else
            {
                                    // If color_1 is not null...
            if ( color_2 == null )
                                    // ...and color_2 is null,
                                    // color_1 is greater.
                {
                return ( 1 );
                }
            else
                {
                                    // ...and color_2 is not
                                    // null, compare the names
                                    // of the two colors
                return ( color_1.Name.CompareTo (
                             color_2.Name ) );
                }
            }
        }

    } // class NameComparer

// ******************************************* class ARGBComparer

public class ARGBComparer : IComparer < Color >
    {

    // ************************************************** Compare

    public int Compare ( Color  color_1,
                         Color  color_2 )
        {

        if ( color_1 == null )
            {
            if ( color_2 == null )
                {
                                    // If color_1 is null and
                                    // color_2 is null, they're
                                    // equal
                return ( 0 );
                }
            else
                {
                                    // If color_1 is null and
                                    // color_2 is not null,
                                    // color_2 is greater.
                return ( -1 );
                }
            }
        else
            {
                                    // If color_1 is not null...
            if ( color_2 == null )
                                    // ...and color_2 is null,
                                    // color_1 is greater.
                {
                return ( 1 );
                }
            else
                {
                                    // ...and color_2 is not
                                    // null, compare the ARGBs
                                    // of the two colors
                uint  ARGB_1;
                uint  ARGB_2;

                ARGB_1 = Utilities.ColorToUIntARGB ( color_1 );
                ARGB_2 = Utilities.ColorToUIntARGB ( color_2 );

                return ( ARGB_1.CompareTo ( ARGB_2 ) );
                }
            }
        }

    } // class ARGBComparer

When the known colors list is sorted, it is used to populate the panel.

C#
// ******************************************* populate_panel

private Panel populate_panel ( )
    {
    Point   color_square_location;
    Size    color_square_size;
    int     column = 0;
    Panel   panel = new Panel ( );

    panel.Location = new Point ( PANEL_LEFT, PANEL_TOP );
    panel.Size = new Size ( PANEL_WIDTH, PANEL_HEIGHT );

    color_square_location = new Point ( INITIAL_LEFT,
                                        INITIAL_TOP );
    color_square_size = new Size ( COLOR_SQUARE_EDGE,
                                   COLOR_SQUARE_EDGE );

    foreach ( Color color in known_colors )
        {
        Button   color_square = new Button ( );
        ToolTip  tooltip = new ToolTip ( );

        color_square.Location = color_square_location;
        color_square.Size = color_square_size;
        color_square.BackColor = color;
        color_square.Click += new System.EventHandler (
                                  color_square_BUT_Click );
        tooltip.SetToolTip ( color_square, color.Name );
        tooltip.AutomaticDelay = TOOLTIP_DELAY;

        panel.Controls.Add ( color_square );
        column++;

        if ( column >= COLOR_SQUARES_PER_ROW )
            {
            column = 0;

            color_square_location.X = INITIAL_LEFT;
            color_square_location.Y +=
                COLOR_SQUARE_EDGE + COLOR_SQUARE_SEPARATION;
            }
        else
            {
            color_square_location.X +=
                COLOR_SQUARE_EDGE + COLOR_SQUARE_SEPARATION;
            }
        }

    return ( panel );
    }

On initialization, the variable sort_by_name is true and the colors by name panel is displayed.

C#
// ******************************************* initialize_GUI

private void initialize_GUI ( )
    {

    if ( sort_by_name )
        {
        byNameToolStripMenuItem.Checked = true;
        sortByNameToolStripMenuItem.Checked = true;
        byARGBToolStripMenuItem.Checked = false;
        sortByARGBToolStripMenuItem.Checked = false;

        colors_by_name_panel.Visible = true;
        colors_by_ARGB_panel.Visible = false;
        }
    else
        {
        byNameToolStripMenuItem.Checked = false;
        sortByNameToolStripMenuItem.Checked = false;
        byARGBToolStripMenuItem.Checked = true;
        sortByARGBToolStripMenuItem.Checked = true;

        colors_by_name_panel.Visible = false;
        colors_by_ARGB_panel.Visible = true;
        }
    }

If the user toggles the display, the variable sort_by_name becomes false and the colors by ARGB panel is displayed.

When a color is selected, the information about the color is displayed.

Known Color Selected

Once a color is selected, either clicking on the color swatch or pressing Ctrl-S causes the color information to be copied to the Clipboard. For the known color DarkRed, the information copied to the Clipboard is:

{Name=DarkRed,ARGB=(255,139,0,0)=#FF8B0000=(FF,8B,00,00)} 

Although the transfer to the Clipboard is not the same as setting the color in Microsoft Paint, it does provide a means by which the data can be captured and copied into Microsoft Paint. If I can figure out how to subclass Microsoft Paint, I will revise the Know Colors Palette Tool to interact directly with Microsoft Paint. Any suggestions for this upgrade would be appreciated.

Revision

As pointed out by a reader, the screen resolution at tool development may not be the same as the screen resolution at tool execution. What looks fine at 1024x768 may not look very well at other resolutions. What is worse is that the tool may become useless as the tool shrinks at higher resolutions.

To address this issue, I redeveloped the tool at a screen resolution of 800x600. Once that was completed, I added code to initialize two screen resolution multipliers, one for horizontal, the other for vertical adjustment.

C#
// ************************ initialize_resolution_multipliers

private void initialize_resolution_multipliers ( )
    {

    if ( ( SystemInformation.PrimaryMonitorSize.Height >
           CREATED_IN_SCREEN_HEIGHT ) ||
         ( SystemInformation.PrimaryMonitorSize.Width >
           CREATED_IN_SCREEN_WIDTH ) )
        {
        screen_height_multiplier =
            ( float ) SystemInformation.
                          PrimaryMonitorSize.Height /
            ( float ) CREATED_IN_SCREEN_HEIGHT;
        screen_height_multiplier *= 4.0F;
        screen_height_multiplier /= 5.0F;

        screen_width_multiplier =
            ( float ) SystemInformation.
                          PrimaryMonitorSize.Width /
            ( float ) CREATED_IN_SCREEN_WIDTH;
        screen_width_multiplier *= 4.0F;
        screen_width_multiplier /= 5.0F;

        color_square_edge =
            ( int ) ( ( float ) color_square_edge *
                      screen_width_multiplier );
        color_square_separation =
            ( int ) ( ( float ) color_square_separation *
                      screen_width_multiplier );

        resolution_changed = true;
        }
    }

In addition to the multipliers, two global variables, color_square_edge and color_square_separation are assigned adjusted values. These two variables replace the constants COLOR_SQUARE_EDGE and COLOR_SQUARE_SEPARATION in the populate_panel method (see above).

Once these multipliers are initialized (note both will be 1.0F if the execution resolution is 800x600), the actual adjustment waits for the Load event to fire, that, in turn, executes the adjust_GUI_to_resolution method.

C#
// ********************************** KnownColorsPalette_Load

private void KnownColorsPalette_Load ( object       sender,
                                       EventArgs    e )
    {
    adjust_GUI_to_resolution ( );
    }

If the execution resolution is different from the execution resolution (i.e., the variable resolution_changed is true), the adjust_GUI_to_resolution method modifies the location, size, and font size of each control.

C#
// ********************************* adjust_GUI_to_resolution

// http://cshark.wordpress.com/2009/06/01/
//    how-to-change-form-size-depending-on-screen-resolution/

private void adjust_GUI_to_resolution ( )
    {

    if ( resolution_changed )
        {
        float   font_size;
        int     height;
        int     width;
        float   x;
        float   y;

        font_size = this.Font.Size *
                    screen_height_multiplier;
        height = ( int ) ( ( float ) this.Height *
                           screen_height_multiplier );
        width = ( int ) ( ( float ) this.Width *
                          screen_height_multiplier );
        x = this.Location.X * screen_width_multiplier;
        y = this.Location.Y * screen_height_multiplier;

        this.Height = height;
        this.Width = width;
        this.Font = new Font ( this.Font.FontFamily,
                               font_size,
                               this.Font.Style );

        foreach ( Control control in this.Controls )
            {
            font_size = control.Font.Size *
                        screen_height_multiplier;
            height = ( int ) ( ( float ) control.Height *
                               screen_height_multiplier );
            width = ( int ) ( ( float ) control.Width *
                              screen_height_multiplier );
            x = control.Location.X * screen_width_multiplier;
            y = control.Location.Y * screen_height_multiplier;

            control.Width = ( int ) Math.Ceiling ( ( double ) width );
            control.Height = ( int ) Math.Ceiling ( ( double ) height );
            control.Location = new Point ( ( int ) x,
                                           ( int ) y );
            control.Font = new Font ( control.Font.FontFamily,
                                      ( int ) font_size,
                                      control.Font.Style );
            }
        }
    }

There is a problem with the font size of tooltips and menu items that I am still researching. When I have a solution, I will again revise this article.

References

History

  • 11/26/2010 - Revised article to address reader's comments and correct typographic and logic errors
  • 11/29/2010 - Revised the tool such that it reacts to execution screen resolutions that differ from the development resolution

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
In 1964, I was in the US Coast Guard when I wrote my first program. It was written in RPG (note no suffixing numbers). Programs and data were entered using punched cards. Turnaround was about 3 hours. So much for the "good old days!"

In 1970, when assigned to Washington DC, I started my MS in Mechanical Engineering. I specialized in Transportation. Untold hours in statistical theory and practice were required, forcing me to use the university computer and learn the FORTRAN language, still using punched cards!

In 1973, I was employed by the Norfolk VA Police Department as a crime analyst for the High Intensity Target program. There, I was still using punched cards!

In 1973, I joined Computer Sciences Corporation (CSC). There, for the first time, I was introduced to a terminal with the ability to edit, compile, link, and test my programs on-line. CSC also gave me the opportunity to discuss technical issues with some of the brightest minds I've encountered during my career.

In 1975, I moved to San Diego to head up an IR&D project, BIODAB. I returned to school (UCSD) and took up Software Engineering at the graduate level. After BIODAB, I headed up a team that fixed a stalled project. I then headed up one of the two most satisfying projects of my career, the Automated Flight Operations Center at Ft. Irwin, CA.

I left Anteon Corporation (the successor to CSC on a major contract) and moved to Pensacola, FL. For a small company I built their firewall, given free to the company's customers. An opportunity to build an air traffic controller trainer arose. This was the other most satisfying project of my career.

Today, I consider myself capable.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey20-Feb-12 21:34
professionalManoj Kumar Choubey20-Feb-12 21:34 
Generalnice one Pin
Pranay Rana17-Jan-11 0:57
professionalPranay Rana17-Jan-11 0:57 
GeneralOn selection of colors Pin
SergeyAndreyev26-Nov-10 21:17
SergeyAndreyev26-Nov-10 21:17 
AnswerRe: On selection of colors Pin
gggustafson27-Nov-10 10:10
mvagggustafson27-Nov-10 10:10 
GeneralRe: On selection of colors Pin
SergeyAndreyev27-Nov-10 21:20
SergeyAndreyev27-Nov-10 21:20 
GeneralRe: On selection of colors Pin
gggustafson29-Nov-10 15:01
mvagggustafson29-Nov-10 15:01 
GeneralMy vote of 1 Pin
Dave Kreskowiak3-May-10 8:40
mveDave Kreskowiak3-May-10 8:40 
GeneralRe: My vote of 1 Pin
gggustafson3-May-10 10:51
mvagggustafson3-May-10 10:51 
QuestionRe: My vote of 1 Pin
gggustafson1-Dec-10 4:44
mvagggustafson1-Dec-10 4:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.