Home Search Contact us About us
Title A Simple Colour Picking ComboBox using OwnerDraw and Reflection.
Summary This simple tutorial demonstrates the using an Owner Draw ComboBox to allow the user to select from a prefined set of colours. The colours are gathered by enumerating the Color and KnowColor objects.
Contributor John McTainsh
Published 1-Apr-2002
Last updated 1-Apr-2002
Page rating   90% for 2 votes Useless Brilliant
 Download Demo - 2 Kb
 Download Full Source - 18 Kb
 Download Demo.exe - 4 Kb

Introduction

Here is a simple drop down ComboBox that allows the operator to select a colour from a predefined set of colours. The code also demonstrates a simple implementation of an Owner draw control and using Reflection to enumerate the available colours. We will cover how to use the control and then for who ever is interested, we will cover how the control works.

How to Install and Use

  1. Open the Project and Solution Explorer.
  2. Right click on the Project in the solution Explorer
  3. Choose the "Add"->"Add Existing Item.." menu.
  4. Browse to the ComboBoxColors.cs file and select it. 
  5. It should appear in the Solution exploder as a Component. There must be a better way to do the following. ( Please email to ComboBoxColors@mctainsh.com
  6. Place a ComboBox on your form.
  7. Close the form and open then source file.
  8. Add #using AntarcticSolutions; to the top of the file.
  9. Replace all instances of System.Windows.Forms.ComboBox with ComboBoxColors. (Be sure to Expand the Windows Form Designer generated code region first) 
  10. In the FormLoad or constructor after the Combobox has been created call LoadBaseColors() or LoadAllWindowsColors() set the colours up in the ComboBox.
  11. At this time you could also set the initial colour with
m_comboBoxColors.LoadAllWindowsColors();
m_comboBoxColors.SelectedColor = Color.Red;

Note: LoadAllWindowsColors() will load all the standard named colours and also load the known Windows colours such as "Menu" and "ScrollBar". If you do not want these colours then call LoadBaseColors().

OwnerDraw

Each item in the ComboBox contains the items colour name as text and a box next to it showing a sample of the colour. To achieve this we use perform the drawing of the control ourselves by setting the controls DrawMode to OwnerDrawFixed and by providing our own implementation of OnDrawItem(...). In the constructor we call the following to set the style and point to our own Drawing method;

DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
DrawItem += new System.Windows.Forms.DrawItemEventHandler( OnDrawItem );

In the following code we draw the colour sample and text string of the colour we are drawing. This method is called for each item that is draw in the list and for the selected item next to the drop down arrow. Note, we try to use as much data as we can from the passed in DrawItemEventArgs. This ensures if the used uses there own background colour or font size, the Colour Combobox will still like all the other standard window controls.

private void OnDrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
    // Fill in the background
    e.Graphics.FillRectangle( new SolidBrush( e.BackColor ), e.Bounds );  
    if( e.Index < 0 )
        return;
    
    // Work out where every thing goes
    int nX = e.Bounds.Left;
    int nY = e.Bounds.Top;
    int nMarg = 2;
    int nH = e.Bounds.Height-(2*nMarg);
    string sText = Items[e.Index].ToString();

    // Draw the Colour Gymph
    Pen penFore = new Pen( e.ForeColor );
    Rectangle rectGymph = new Rectangle( nX+nMarg, nY+nMarg, nH, nH );
    e.Graphics.FillRectangle( new SolidBrush( Color.FromName( sText ) ), rectGymph );  
    e.Graphics.DrawRectangle( penFore, rectGymph );  

    // Draw the text
    e.Graphics.DrawString( 
        sText, e.Font, new SolidBrush( e.ForeColor ), 
        nX + nH + (2*nMarg), e.Bounds.Top );
}

Get the List of Available Colours

The Color structure contains a list of predefined colours in the form of public static properties and the KnownColor enumerator defines a set of named and system colours. Each is used as follows;

Color clrRaceCar = Color.Red;
Color clrFrame   = Color.FromKnownColor( KnownColor.ActiveBorder );

To populate the ComboBox with these colours we need a list of them. To do this we use reflection to add the items to the Combobox Items collection as follows; 

using System.Drawing;
using System.Reflection;
...

public void LoadBaseColors()
{
    Items.Clear();
    PropertyInfo [] aryPI = typeof( Color ).GetProperties( 
        BindingFlags.Public | BindingFlags.Static );
    foreach( PropertyInfo pi in aryPI )
        Items.Add( pi.Name );
}

public void LoadAllWindowsColors()
{
    Items.Clear();
    FieldInfo [] aryPI = typeof( KnownColor ).GetFields( 
        BindingFlags.Public | BindingFlags.Static );
    foreach( FieldInfo pi in aryPI )
        Items.Add( pi.Name );
}

Note: for the enumerator we use FieldInfo and for the structure we use the PropertyInfo class;

Conclusion

With a relatively small amount of code we have been able to enumerate all the colours and draw then in a ComboBox. This method class could also be altered to show graphic line types or line widths for user selection.

Comments Date
Home Search Contact us About us