Click here to Skip to main content
15,886,518 members
Articles / Programming Languages / C#
Article

MS Office Style Colour-Picker Dialog

Rate me:
Please Sign up or sign in to vote.
4.40/5 (15 votes)
14 Jan 20032 min read 105.8K   754   55   10
A clone of the font color dialog like found at Microsoft Word.

Sample Image - color_picker.gif

Introduction

For a project I'm working on I needed something more stylish than the standard color dialog which comes with .NET, so I decided to make a color picker dialog of my own. I used the one found in the Microsoft Office suite (for choosing the font color) as a source of inspiration. I used exactly the same palette of 40 colors and almost the same "look and feel" - only the size and distance of the little color panels is a little different in my version.

Using the code

The code for the color dialog is very straightforward and offers nothing exciting. It should be self-explaining. The control is a form with 40 square little panel controls, which have event handlers for mouse messages attached to them. The constructor receives the coordinates of the point it is supposed to appear at as arguments (usually the calling button of the container form). When closed, the color dialog returns the chosen color. The dialog can alternatively be closed by hitting Escape or Enter (by using an "invisible" Escape button).

The demo project consists of three classes:

  • ColorPaletteDialog,
  • ColorButton and
  • MainForm
The code on this pages shows only the ColorPaletteDialog class, which is the most interesting. The other two can be found in the distributable archive, along with a compiled *.exe.

The ColorButton class (derived from the Button class) is used in order to display the last chosen color on its center. You can use the Color attribute of an ordinary button too, but I wanted to have a border around it and the little arrow, indicating further options, like found at the color picker for the color schemes of the Windows desktop. For the color display a new attribute "CenterColor" was added to the derived class.

The example form features three ColorButton instances, using different sizes and different styles (popup, flat and normal). The ColorButton_Click event handler checks which button is the sender of the message and acts accordingly. A standard color dialog is called from the "More colors..." button, as usual.

C#
public class ColorPaletteDialog : Form
{
    byte max = 40;
    Panel[] panel = new Panel[40];

    Color[] color = new Color[40]
    {
        //row 1
        Color.FromArgb(0,0,0), Color.FromArgb(153,51,0),
        Color.FromArgb(51,51,0), Color.FromArgb(0,51,0),
        Color.FromArgb(0,51,102), Color.FromArgb(0,0,128),
        Color.FromArgb(51,51,153), Color.FromArgb(51,51,51),

        //row 2
        Color.FromArgb(128,0,0), Color.FromArgb(255,102,0),
        Color.FromArgb(128,128,0), Color.FromArgb(0,128,0),
        Color.FromArgb(0,128,128), Color.FromArgb(0,0,255),
        Color.FromArgb(102,102,153), Color.FromArgb(128,128,128),

        //row 3
        Color.FromArgb(255,0,0), Color.FromArgb(255,153,0),
        Color.FromArgb(153,204,0), Color.FromArgb(51,153,102),
        Color.FromArgb(51,204,204), Color.FromArgb(51,102,255),
        Color.FromArgb(128,0,128), Color.FromArgb(153,153,153),

        //row 4
        Color.FromArgb(255,0,255), Color.FromArgb(255,204,0),
        Color.FromArgb(255,255,0), Color.FromArgb(0,255,0),
        Color.FromArgb(0,255,255), Color.FromArgb(0,204,255),
        Color.FromArgb(153,51,102), Color.FromArgb(192,192,192),

        //row 5
        Color.FromArgb(255,153,204), Color.FromArgb(255,204,153),
        Color.FromArgb(255,255,153), Color.FromArgb(204,255,204),
        Color.FromArgb(204,255,255), Color.FromArgb(153,204,255),
        Color.FromArgb(204,153,255), Color.FromArgb(255,255,255)
    };

    string[] colorName = new string[40]
    {
        "Black", "Brown", "Olive Green", "Dark Green", "Dark Teal",
        "Dark Blue", "Indigo", "Gray-80%","Dark Red", "Orange",
        "Dark Yellow", "Green", "Teal", "Blue", "Blue-Gray", "Gray-50%",
        "Red", "Light Orange", "Lime", "Sea Green", "Aqua", "Light Blue",
        "Violet", "Gray-40%","Pink", "Gold", "Yellow", "Bright Green",
        "Turquoise", "Sky Blue", "Plum", "Gray-25%", "Rose", "Tan",
        "Light Yellow", "Light Green", "Light Turquoise", "Pale Blue",
        "Lavender", "White"
    };

    Button moreColorsButton = new Button();
    Button cancelButton = new Button();
    Color selectedColor;

    public ColorPaletteDialog(int x, int y)
    {
        Size = new Size(158, 132);
        FormBorderStyle = FormBorderStyle.FixedDialog;
        MinimizeBox = MaximizeBox = ControlBox = false;
        ShowInTaskbar = false;
        CenterToScreen();
        Location = new Point(x, y);

        BuildPalette();

        moreColorsButton.Text = "More colors ...";
        moreColorsButton.Size = new Size(142, 22);
        moreColorsButton.Location = new Point(5, 99);
        moreColorsButton.Click += new EventHandler(moreColorsButton_Click);
        moreColorsButton.FlatStyle = FlatStyle.Popup;
        Controls.Add(moreColorsButton);

        //"invisible" button to cancel at Escape
        cancelButton.Size = new Size(5, 5);
        cancelButton.Location = new Point(-10, -10);
        cancelButton.Click += new EventHandler(cancelButton_Click);
        Controls.Add(cancelButton);
        cancelButton.TabIndex = 0;
        cancelButton.DialogResult = DialogResult.Cancel;
        this.CancelButton = cancelButton;
    }

    public Color Color
    {
        get {return selectedColor;}
    }

    void BuildPalette()
    {
        byte pwidth = 16;
        byte pheight = 16;
        byte pdistance = 2;
        byte border = 5;
        int x = border, y = border;
        ToolTip toolTip = new ToolTip();

        for(int i = 0; i < max; i++)
        {
            panel[i] = new Panel();
            panel[i].Height = pwidth;
            panel[i].Width = pheight;
            panel[i].Location = new Point(x, y);
            toolTip.SetToolTip(panel[i], colorName[i]);

            this.Controls.Add(panel[i]);

            if(x < ( 7 * (pwidth + pdistance)))
                x += pwidth + pdistance;
            else
            {
                x = border;
                y += pheight + pdistance;
            }

            panel[i].BackColor = color[i];
            panel[i].MouseEnter += new EventHandler(OnMouseEnterPanel);
            panel[i].MouseLeave += new EventHandler(OnMouseLeavePanel);
            panel[i].MouseDown += new MouseEventHandler(OnMouseDownPanel);
            panel[i].MouseUp += new MouseEventHandler(OnMouseUpPanel);
            panel[i].Paint += new PaintEventHandler(OnPanelPaint);
        }
    }

    void moreColorsButton_Click(object sender, System.EventArgs e)
    {
        ColorDialog colDialog = new ColorDialog();
        colDialog.FullOpen = true;
        if(colDialog.ShowDialog() == DialogResult.OK)
        {
               selectedColor = colDialog.Color;
               DialogResult = DialogResult.OK;
        }
        colDialog.Dispose();

        Close();
    }

    void cancelButton_Click(object sender, System.EventArgs e)
    {
        Close();
    }

    void OnMouseEnterPanel(object sender, EventArgs e)
    {
        DrawPanel(sender, 1);
    }

    void OnMouseLeavePanel(object sender, EventArgs e)
    {
        DrawPanel(sender, 0);
    }

    void OnMouseDownPanel(object sender, MouseEventArgs e)
    {
        DrawPanel(sender, 2);
    }

    void OnMouseUpPanel(object sender, MouseEventArgs e)
    {
        Panel panel = (Panel)sender;
        selectedColor = panel.BackColor;
        DialogResult = DialogResult.OK;
        Close();
    }

    void DrawPanel(object sender, byte state)
    {
        Panel panel = (Panel)sender;

        Graphics g = panel.CreateGraphics();

        Pen pen1, pen2;

        if(state == 1)         //mouse over
        {
            pen1 = new Pen( SystemColors.ControlLightLight );
            pen2 = new Pen( SystemColors. ControlDarkDark);
        }
        else if(state == 2)    //clicked
        {
            pen1 = new Pen( SystemColors.ControlDarkDark );
            pen2 = new Pen( SystemColors.ControlLightLight );
        }
        else               //neutral
        {
            pen1 = new Pen( SystemColors.ControlDark );
            pen2 = new Pen( SystemColors.ControlDark );

        }

        Rectangle r = panel.ClientRectangle;
        Point p1 = new Point( r.Left, r.Top );          //top left
        Point p2 = new Point( r.Right -1, r.Top );          //top right
        Point p3 = new Point( r.Left, r.Bottom -1 );        //bottom left
        Point p4 = new Point( r.Right -1, r.Bottom -1 );    //bottom right

        g.DrawLine( pen1, p1, p2 );
        g.DrawLine( pen1, p1, p3 );
        g.DrawLine( pen2, p2, p4 );
        g.DrawLine( pen2, p3, p4 );
    }

    void OnPanelPaint(Object sender, PaintEventArgs e)
    {
        DrawPanel(sender, 0);
    }
}

Points of Interest

The little panels show the name of the selected color under the curser inside a tooltip. They also change their appearance, when the mouse hovers over them or clicks them. In order to do this, the Paint method for the panel is overloaded and we draw the borders of the panel ourselves (using System colors), dependant of the state of the mouse.

The project was developed with the free .NET IDE SharpDevelop (www.icsharpcode.net).
Visit my Homepage www.programming.de for more example code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralToolbar Button Pin
rocketman22118-Dec-10 13:31
rocketman22118-Dec-10 13:31 
GeneralFocus Problems... Pin
FreewareFire26-Apr-06 4:58
FreewareFire26-Apr-06 4:58 
GeneralRe: Focus Problems... Pin
Johannes Wallroth27-Apr-06 5:29
Johannes Wallroth27-Apr-06 5:29 
AnswerRe: Focus Problems... Pin
FreewareFire27-Apr-06 12:31
FreewareFire27-Apr-06 12:31 
Hi Johannes!

You didn't test this solution clean enough... This i've tried also, but try to hover on the "Get more Colors..." Button also closes the Form! This happens why hovering the button, the form also lose the Focus! But i think you know that!

I've come up with something like that...

<br />
        bool CouldCancel = true;<br />
        private void button1_Click(object sender, EventArgs e)<br />
        {<br />
            CouldCancel = false;<br />
<br />
            if (clDialog.ShowDialog() == DialogResult.OK)<br />
            {<br />
                CouldCancel = true;<br />
                this.Close();<br />
            }<br />
            else if (clDialog.ShowDialog() == DialogResult.Cancel)<br />
            {<br />
                CouldCancel = true;<br />
                this.Close();<br />
            }<br />
<br />
        }<br />
<br />
        private void ColorForm_Deactivate(object sender, EventArgs e)<br />
        {<br />
            if (CouldCancel == true)<br />
            {<br />
                this.Dispose();<br />
                this.Close();<br />
            }<br />
        }<br />


button1 is the "Get more Colors" Button, clDialog the ColorDialog!

the CouldCancel is only set to false if we are open the ColorDialog (if it's not false, the Dialog wouldn't appear!)

but it should self explaining?! If someone has a question, please feel free to ask! The advance of the variable is simply that you don't need a timer!

Hope this helps!

Greets! Smile | :)

FreewareFire is in the House!
GeneralRe: Focus Problems... Pin
Johannes Wallroth27-Apr-06 21:10
Johannes Wallroth27-Apr-06 21:10 
GeneralRe: Focus Problems... Pin
FreewareFire28-Apr-06 11:25
FreewareFire28-Apr-06 11:25 
GeneralAwesome! Pin
dzCepheus2-Jan-06 11:32
dzCepheus2-Jan-06 11:32 
GeneralRe: Awesome! Pin
loid grey manuel26-Aug-10 21:11
loid grey manuel26-Aug-10 21:11 
QuestionDo you have VC++/ MFC code for this ? Pin
akulkarni23-Feb-04 2:06
akulkarni23-Feb-04 2:06 
Questioncache those rectangles ? Pin
Bill Woodruff11-Dec-02 1:11
Bill Woodruff11-Dec-02 1:11 

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.