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

Button derived color selection control in C#

Rate me:
Please Sign up or sign in to vote.
4.21/5 (15 votes)
22 Dec 20031 min read 82.5K   1.2K   31   8
Button derived color selection control similar to the one used in MS Office applications.

Sample Image - ColorButton.gif

Introduction

ColorButton is a color selection control derived from System.Windows.Forms.Button similar to the one used in MS Office applications. It uses the same colors like MS Office, including support for "Automatic" and "More Colors".

How To Use

Add a normal Button to your Windows Form and set the Text property to an empty string. Then manually change all occurrences of System.Windows.Forms.Button to ColorButton.ColorButton for this button in the source file.

Properties

ColorButton adds the following new properties:

Color (get/set)

Gets or sets the selected color. System.Drawing.Color.Transparent is used for the "Automatic" color.

Automatic (get/set)

Gets or sets the string for the "Automatic" button. Setting this to an empty string disables the "Automatic" color feature.

MoreColors (get/set)

Gets or sets the string for the "More Colors" button. Setting this to an empty string disables the "More Colors" color feature.

Events

ColorButton adds the following new event:

Changed

This event occurs whenever the user changes the selected color. Use the Color property to determine what the selected color is.

History

  • 1.1
    • Added keyboard support to color panel (thanks to Ignazio Di Napoli)
    • Button handles disabled state correctly
    • Button is drawn pushed, if color panel is visible
  • 1.0
    • Initial release

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
Austria Austria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to use this in VB Pin
J3ssy Pmntra29-Sep-14 6:13
J3ssy Pmntra29-Sep-14 6:13 
GeneralFixed Control for Clipregion Pin
CodeMonkey3315-Sep-06 6:23
CodeMonkey3315-Sep-06 6:23 
GeneralReworked as a .NET 2.0 ToolStripButton Pin
Los Guapos7-Mar-06 3:37
Los Guapos7-Mar-06 3:37 
I needed a color picker that worked on a .NET toolbar ToolStrip. This was close but needed some changes. Here is my revised class:

public class ToolStripColorButton : ToolStripButton<br />
{<br />
    private System.ComponentModel.Container components = null ;<br />
<br />
    private Color buttonColor = Color.Transparent ;<br />
    private string autoButton = "Automatic" ;<br />
    private string moreButton = "More Colors..." ;<br />
<br />
    public event EventHandler Changed ;<br />
<br />
    public Color Color<br />
    {<br />
        get { return buttonColor ; }<br />
        set <br />
		{ <br />
			buttonColor = value ;<br />
			Invalidate();<br />
		}<br />
    }<br />
<br />
    public string Automatic<br />
    {<br />
        get { return autoButton ; }<br />
        set { autoButton = value ; }<br />
    }<br />
<br />
    public string MoreColors<br />
    {<br />
        get { return moreButton ; }<br />
        set { moreButton = value ; }<br />
    }<br />
<br />
	public bool DroppedDown<br />
	{<br />
		get { return this.Checked; }<br />
	}<br />
<br />
    protected virtual void OnChanged( EventArgs e )<br />
    {<br />
        if( Changed != null )<br />
            Changed( this, e ) ;<br />
    }<br />
<br />
	public ToolStripColorButton()<br />
    {<br />
		InitializeComponent();<br />
    }<br />
<br />
    protected override void Dispose( bool disposing )<br />
    {<br />
        if( disposing )<br />
        {<br />
            if( components != null )<br />
                components.Dispose() ;<br />
        }<br />
<br />
        base.Dispose( disposing ) ;<br />
    }<br />
<br />
    #region Vom Komponenten-Designer generierter Code<br />
    private void InitializeComponent()<br />
    {<br />
        components = new System.ComponentModel.Container() ;<br />
    }<br />
    #endregion<br />
<br />
    protected override void OnPaint( PaintEventArgs e )<br />
    {<br />
        base.OnPaint( e ) ;<br />
<br />
		int offset = 0;<br />
<br />
		Rectangle rc = new Rectangle(e.ClipRectangle.Left + 5 + offset,<br />
									  e.ClipRectangle.Top + 5 + offset,<br />
									  e.ClipRectangle.Width - 20,<br />
									  e.ClipRectangle.Height - 11);<br />
		Pen darkPen = new Pen(SystemColors.ControlDark);<br />
<br />
		if (Enabled)<br />
		{<br />
			e.Graphics.FillRectangle(new SolidBrush(buttonColor), rc);<br />
			e.Graphics.DrawRectangle(darkPen, rc);<br />
		}<br />
<br />
		Pen textPen = new Pen(Enabled ? SystemColors.ControlText : SystemColors.GrayText);<br />
		Point pt = new Point(rc.Right, (e.ClipRectangle.Height + offset) / 2);<br />
<br />
		e.Graphics.DrawLine(textPen, pt.X + 5, pt.Y - 1, pt.X + 9, pt.Y - 1);<br />
		e.Graphics.DrawLine(textPen, pt.X + 6, pt.Y, pt.X + 8, pt.Y);<br />
		e.Graphics.DrawLine(textPen, pt.X + 7, pt.Y, pt.X + 7, pt.Y + 1);<br />
    }<br />
<br />
    protected override void OnClick( EventArgs e )<br />
    {<br />
		this.Checked = true;<br />
		Invalidate();<br />
<br />
        Point pt = Parent.PointToScreen( new Point( this.Bounds.X, this.Bounds.Y + this.Bounds.Height ) ) ;<br />
<br />
        ColorPanel panel = new ColorPanel( pt, this ) ;<br />
        panel.Show() ;<br />
    }<br />
<br />
    protected class ColorPanel : System.Windows.Forms.Form<br />
    {<br />
		private ToolStripColorButton colorButton;<br />
        private int colorIndex = -1 ;<br />
        // ADDED: Ignazio Di Napoli - neclepsio@hotmail.com<br />
        private int keyboardIndex = -50 ;<br />
        // END ADDED<br />
<br />
        private Color[] colorList = new Color[40]<br />
        {<br />
            Color.FromArgb( 0x00, 0x00, 0x00 ), Color.FromArgb( 0x99, 0x33, 0x00 ),<br />
            Color.FromArgb( 0x33, 0x33, 0x00 ), Color.FromArgb( 0x00, 0x33, 0x00 ),<br />
            Color.FromArgb( 0x00, 0x33, 0x66 ), Color.FromArgb( 0x00, 0x00, 0x80 ),<br />
            Color.FromArgb( 0x33, 0x33, 0x99 ), Color.FromArgb( 0x33, 0x33, 0x33 ),<br />
<br />
            Color.FromArgb( 0x80, 0x00, 0x00 ), Color.FromArgb( 0xFF, 0x66, 0x00 ),<br />
            Color.FromArgb( 0x80, 0x80, 0x00 ), Color.FromArgb( 0x00, 0x80, 0x00 ),<br />
            Color.FromArgb( 0x00, 0x80, 0x80 ), Color.FromArgb( 0x00, 0x00, 0xFF ),<br />
            Color.FromArgb( 0x66, 0x66, 0x99 ), Color.FromArgb( 0x80, 0x80, 0x80 ),<br />
<br />
            Color.FromArgb( 0xFF, 0x00, 0x00 ), Color.FromArgb( 0xFF, 0x99, 0x00 ),<br />
            Color.FromArgb( 0x99, 0xCC, 0x00 ), Color.FromArgb( 0x33, 0x99, 0x66 ),<br />
            Color.FromArgb( 0x33, 0xCC, 0xCC ), Color.FromArgb( 0x33, 0x66, 0xFF ),<br />
            Color.FromArgb( 0x80, 0x00, 0x80 ), Color.FromArgb( 0x99, 0x99, 0x99 ),<br />
<br />
            Color.FromArgb( 0xFF, 0x00, 0xFF ), Color.FromArgb( 0xFF, 0xCC, 0x00 ),<br />
            Color.FromArgb( 0xFF, 0xFF, 0x00 ), Color.FromArgb( 0x00, 0xFF, 0x00 ),<br />
            Color.FromArgb( 0x00, 0xFF, 0xFF ), Color.FromArgb( 0x00, 0xCC, 0xFF ),<br />
            Color.FromArgb( 0x99, 0x33, 0x66 ), Color.FromArgb( 0xC0, 0xC0, 0xC0 ),<br />
<br />
            Color.FromArgb( 0xFF, 0x99, 0xCC ), Color.FromArgb( 0xFF, 0xCC, 0x99 ),<br />
            Color.FromArgb( 0xFF, 0xFF, 0x99 ), Color.FromArgb( 0xCC, 0xFF, 0xCC ),<br />
            Color.FromArgb( 0xCC, 0xFF, 0xFF ), Color.FromArgb( 0x99, 0xCC, 0xFF ),<br />
            Color.FromArgb( 0xCC, 0x99, 0xFF ), Color.FromArgb( 0xFF, 0xFF, 0xFF )<br />
        } ;<br />
<br />
		public ColorPanel(Point pt, ToolStripColorButton button)<br />
        {<br />
            colorButton = button ;<br />
<br />
            FormBorderStyle = FormBorderStyle.FixedDialog ;<br />
            MinimizeBox = false ;<br />
            MaximizeBox = false ;<br />
            ControlBox = false ;<br />
            ShowInTaskbar = false ;<br />
            TopMost = true ;<br />
<br />
            SetStyle( ControlStyles.DoubleBuffer, true ) ;<br />
            SetStyle( ControlStyles.UserPaint, true ) ;<br />
            SetStyle( ControlStyles.AllPaintingInWmPaint, true ) ;<br />
<br />
            Width = 156 ;<br />
            Height = 100 ;<br />
<br />
            if( colorButton.autoButton != "" )<br />
                Height += 23 ;<br />
            if( colorButton.moreButton != "" )<br />
                Height += 23 ;<br />
<br />
            CenterToScreen() ;<br />
            Location = pt ;<br />
<br />
            Capture = true ;<br />
        }<br />
<br />
        protected override void OnClosed( EventArgs e )<br />
        {<br />
            base.OnClosed( e ) ;<br />
<br />
			colorButton.Checked = false;<br />
			colorButton.Invalidate();<br />
        }<br />
<br />
        protected override void OnPaint( PaintEventArgs e )<br />
        {<br />
            base.OnPaint( e ) ;<br />
<br />
            Pen darkPen = new Pen( SystemColors.ControlDark ) ;<br />
            Pen lightPen = new Pen( SystemColors.ControlLightLight ) ;<br />
            SolidBrush lightBrush = new SolidBrush( SystemColors.ControlLightLight ) ;<br />
            bool selected = false ;<br />
            int x = 6, y = 5 ;<br />
<br />
            if( colorButton.autoButton != "" )<br />
            {<br />
                selected = colorButton.Color == Color.Transparent ;<br />
                DrawButton( e, x, y, colorButton.autoButton, 100, selected ) ;<br />
                y += 23 ;<br />
            }<br />
<br />
            for( int i = 0 ; i < 40 ; i++ )<br />
            {<br />
                if( colorButton.Color.ToArgb() == colorList[i].ToArgb() )<br />
                    selected = true ;<br />
<br />
                if( colorIndex == i )<br />
                {<br />
                    e.Graphics.DrawRectangle( lightPen, x - 3, y - 3, 17, 17 ) ;<br />
                    e.Graphics.DrawLine( darkPen, x - 2, y + 14, x + 14, y + 14 ) ;<br />
                    e.Graphics.DrawLine( darkPen, x + 14, y - 2, x + 14, y + 14 ) ;<br />
                }<br />
                else if( colorButton.Color.ToArgb() == colorList[i].ToArgb() )<br />
                {<br />
                    // ADDED: Ignazio Di Napoli - neclepsio@hotmail.com<br />
                    if( keyboardIndex == -50 )<br />
                        keyboardIndex = i ;<br />
                    // END ADDED<br />
<br />
                    e.Graphics.FillRectangle( lightBrush, x - 3, y - 3, 18, 18 ) ;<br />
                    e.Graphics.DrawLine( darkPen, x - 3, y - 3, x + 13, y - 3 ) ;<br />
                    e.Graphics.DrawLine( darkPen, x - 3, y - 3, x - 3, y + 13 ) ;<br />
                }<br />
<br />
                e.Graphics.FillRectangle( new SolidBrush( colorList[i] ), x, y, 11, 11 ) ;<br />
                e.Graphics.DrawRectangle( darkPen, x, y, 11, 11 ) ;<br />
<br />
                if( ( i + 1 ) % 8 == 0 )<br />
                {<br />
                    x = 6 ;<br />
                    y += 18 ;<br />
                }<br />
                else<br />
                    x += 18 ;<br />
            }<br />
<br />
            if( colorButton.moreButton != "" )<br />
                DrawButton( e, x, y, colorButton.moreButton, 101, ! selected ) ;<br />
        }<br />
<br />
        // ADDED: Ignazio Di Napoli - neclepsio@hotmail.com<br />
        protected override void OnKeyDown( KeyEventArgs e )<br />
        {<br />
            if( e.KeyCode == Keys.Escape )<br />
                Close() ;<br />
            else if( e.KeyCode == Keys.Left )<br />
                MoveIndex( -1 ) ;<br />
            else if( e.KeyCode == Keys.Up )<br />
                MoveIndex( -8 ) ;<br />
            else if( e.KeyCode == Keys.Down )<br />
                MoveIndex( +8 ) ;<br />
            else if( e.KeyCode == Keys.Right )<br />
                MoveIndex( +1 ) ;<br />
            else if( e.KeyCode == Keys.Enter ||<br />
                     e.KeyCode == Keys.Space )<br />
                OnClick( EventArgs.Empty ) ;<br />
            else<br />
                base.OnKeyDown( e ) ;<br />
        }<br />
<br />
        private void MoveIndex( int delta )<br />
        {<br />
            int lbound = ( colorButton.autoButton != "" ? -8 : 0 ) ;<br />
            int ubound = 39 + ( colorButton.moreButton != "" ? 8 : 0 ) ;<br />
            int d = ubound - lbound + 1 ;<br />
<br />
            if( delta == -1 && keyboardIndex < 0 )<br />
                keyboardIndex = ubound ;<br />
            else if( delta == 1 && keyboardIndex > 39 )<br />
                keyboardIndex = lbound ;<br />
            else if( delta == 1 && keyboardIndex < 0 )<br />
                keyboardIndex = 0 ;<br />
            else if( delta == -1 && keyboardIndex > 39 )<br />
                keyboardIndex = 39 ;<br />
            else<br />
                keyboardIndex += delta ;<br />
<br />
            if( keyboardIndex < lbound )<br />
                keyboardIndex += d ;<br />
            if( keyboardIndex > ubound )<br />
                keyboardIndex -= d ;<br />
<br />
            if( keyboardIndex < 0 )<br />
                colorIndex = 100 ;<br />
            else if( keyboardIndex > 39 )<br />
                colorIndex = 101 ;<br />
            else<br />
                colorIndex = keyboardIndex ;<br />
<br />
            Refresh() ;<br />
        }<br />
        // END ADDED<br />
<br />
        protected override void OnMouseDown( MouseEventArgs e )<br />
        {<br />
            if( RectangleToScreen( ClientRectangle ).Contains( Cursor.Position ) )<br />
                base.OnMouseDown( e ) ;<br />
            else<br />
                Close() ;<br />
        }<br />
<br />
        protected override void OnMouseMove( MouseEventArgs e )<br />
        {<br />
            base.OnMouseMove( e ) ;<br />
<br />
            if( RectangleToScreen( ClientRectangle ).Contains( Cursor.Position ) )<br />
            {<br />
                Point pt = PointToClient( Cursor.Position ) ;<br />
                int x = 6, y = 5 ;<br />
<br />
                if( colorButton.autoButton != "" )<br />
                {<br />
                    if( SetColorIndex( new Rectangle( x - 3, y - 3, 143, 22 ), pt, 100 ) )<br />
                        return ;<br />
<br />
                    y += 23 ;<br />
                }<br />
<br />
                for( int i = 0 ; i < 40 ; i++ )<br />
                {<br />
                    if( SetColorIndex( new Rectangle( x - 3, y - 3, 17, 17 ), pt, i ) )<br />
                        return ;<br />
<br />
                    if( ( i + 1 ) % 8 == 0 )<br />
                    {<br />
                        x = 6 ;<br />
                        y += 18 ;<br />
                    }<br />
                    else<br />
                        x += 18 ;<br />
                }<br />
<br />
                if( colorButton.moreButton != "" )<br />
                {<br />
                    if( SetColorIndex( new Rectangle( x - 3, y - 3, 143, 22 ), pt, 101 ) )<br />
                        return ;<br />
                }<br />
            }<br />
<br />
            if( colorIndex != -1 )<br />
            {<br />
                colorIndex = -1 ;<br />
                Invalidate() ;<br />
            }<br />
        }<br />
<br />
        protected override void OnClick( EventArgs e )<br />
        {<br />
            if( colorIndex < 0 )<br />
                return ;<br />
<br />
            if( colorIndex < 40 )<br />
                colorButton.Color = colorList[colorIndex] ;<br />
            else if( colorIndex == 100 )<br />
                colorButton.Color = Color.Transparent ;<br />
            else<br />
            {<br />
                ColorDialog dlg = new ColorDialog() ;<br />
                dlg.Color = colorButton.Color ;<br />
                dlg.FullOpen = true ;<br />
<br />
                if( dlg.ShowDialog( this ) != DialogResult.OK )<br />
                {<br />
                    Close() ;<br />
                    return ;<br />
                }<br />
<br />
                colorButton.Color = dlg.Color ;<br />
            }<br />
<br />
            Close() ;<br />
            colorButton.OnChanged( EventArgs.Empty ) ;<br />
        }<br />
<br />
        protected void DrawButton( PaintEventArgs e, int x, int y, string text,<br />
                                   int index, bool selected )<br />
        {<br />
            Pen darkPen = new Pen( SystemColors.ControlDark ) ;<br />
            Pen lightPen = new Pen( SystemColors.ControlLightLight ) ;<br />
            SolidBrush lightBrush = new SolidBrush( SystemColors.ControlLightLight ) ;<br />
<br />
            if( colorIndex == index )<br />
            {<br />
                e.Graphics.DrawRectangle( lightPen, x - 3, y - 3, 143, 22 ) ;<br />
                e.Graphics.DrawLine( darkPen, x - 2, y + 19, x + 140, y + 19 ) ;<br />
                e.Graphics.DrawLine( darkPen, x + 140, y - 2, x + 140, y + 19 ) ;<br />
            }<br />
            else if( selected )<br />
            {<br />
                e.Graphics.FillRectangle( lightBrush, x - 3, y - 3, 144, 23 ) ;<br />
                e.Graphics.DrawLine( darkPen, x - 3, y - 3, x + 139, y - 3 ) ;<br />
                e.Graphics.DrawLine( darkPen, x - 3, y - 3, x - 3, y + 18 ) ;<br />
            }<br />
<br />
            Rectangle rc = new Rectangle( x, y, 137, 16 ) ;<br />
            SolidBrush textBrush = new SolidBrush( SystemColors.ControlText ) ;<br />
<br />
            StringFormat textFormat = new StringFormat() ;<br />
            textFormat.Alignment = StringAlignment.Center ;<br />
            textFormat.LineAlignment = StringAlignment.Center ;<br />
<br />
            e.Graphics.DrawRectangle( darkPen, rc ) ;<br />
            e.Graphics.DrawString( text, colorButton.Font, textBrush, rc, textFormat ) ;<br />
        }<br />
<br />
        protected bool SetColorIndex( Rectangle rc, Point pt, int index )<br />
        {<br />
            if( rc.Contains( pt ) )<br />
            {<br />
                if( colorIndex != index )<br />
                {<br />
                    colorIndex = index ;<br />
                    Invalidate() ;<br />
                }<br />
<br />
                return true ;<br />
            }<br />
<br />
            return false ;<br />
        }<br />
    }<br />
}

GeneralRe: Reworked as a .NET 2.0 ToolStripButton Pin
shlomifr7-Aug-09 3:05
shlomifr7-Aug-09 3:05 
GeneralVisual Effects Pin
Anthony D.29-Aug-04 8:46
Anthony D.29-Aug-04 8:46 
GeneralNice Job Pin
Tom Spink22-Dec-03 7:08
Tom Spink22-Dec-03 7:08 
GeneralRe: Nice Job Pin
Thomas Ascher22-Dec-03 23:22
Thomas Ascher22-Dec-03 23:22 
GeneralRe: Nice Job Pin
Tom Spink23-Dec-03 0:06
Tom Spink23-Dec-03 0:06 

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.