Confessions of a .NET Developer!

How to use Owner Drawn Controls

There are few controls which support Owner-drawing such as ListBox, ListView,
TreeView, Combobox to name a few. With owner-drawing, you can manipulate the individual items in the above mentioned controls. Each item can be painted using the Graphics object.

In our example, we will use a Listbox having a list of all names of Brushes. Then we will supply the BackColor of each item based on the item’s text(name of Brush).
First step is to set the DrawMode property which takes the DrawMode enum as value. It has three options:
1)Normal – Drawn by operating system, not in our control.
2)OwnerDrawFixed – To be drawn by using our logic with the condition that all the items will be having the same height and width.
3)OwnerDrawVariable – Same as OwnerDrawFixed except that we have to supply the logic for height and width.

Normal won’t be of use in this example as we are going to apply our own logic for drawing of items.
Lets consider using OwnerDrawFixed.
Now to draw the items, we would have to use DrawItem event of ListBox.

Before that, first let us load all the names of the Brushes in the ListBox.

        void Form1_Load(object sender, EventArgs e)
        {
            foreach (PropertyInfo info in typeof(Brushes).GetProperties())
            {
                listBox1.Items.Add(info.Name);
            }
        }

We are using Reflection here to get all the properties and adding each property’s name in to the ListBox.

This is how the window will look like:

SimpleView

SimpleView

Our next task is to give a Background Color for each item in the ListBox depending on the item’s text. For that we will set the DrawMode of ListBox1.

listBox1.DrawMode = DrawMode.OwnerDrawFixed;

Next use the DrawItem event.

listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);

And the method definition:

void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    Brush brush;
    // Take the text from the current listbox item
    string text = listBox1.Items[e.Index].ToString();
    brush = new SolidBrush(Color.FromName(text));
    // Fill the background
    e.Graphics.FillRectangle(brush, e.Bounds);
    // Display the text using the default font and with black foreground
    e.Graphics.DrawString(text, e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y);
}

And our window will look like this:

OwnerDrawFixed

OwnerDrawFixed

But one small issue is the spacing, the items are closely spaced. Lets provide more spacing by increasing the height of each item. For that we have to set the DrawMode property to OwnerDrawVariable.

listBox1.DrawMode = DrawMode.OwnerDrawVariable;

Our DrawItem event will remain the same but we have to use an additional event “MeasureItem” to alter the height.

listBox1.MeasureItem += new MeasureItemEventHandler(listBox1_MeasureItem);

And the method definition:

void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
{
   e.ItemHeight = 20;            
}

So now our final window will look like this:

OwnerDrawVariable

OwnerDrawVariable

This is the final source code:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);
            //listBox1.DrawMode = DrawMode.OwnerDrawFixed;
            listBox1.DrawMode = DrawMode.OwnerDrawVariable;
            listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);
            listBox1.MeasureItem += new MeasureItemEventHandler(listBox1_MeasureItem);
        }

        void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            e.ItemHeight = 20;            
        }

        void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            Brush brush;
            string text = listBox1.Items[e.Index].ToString();
            brush = new SolidBrush(Color.FromName(text));
            e.Graphics.FillRectangle(brush, e.Bounds);

            e.Graphics.DrawString(text, e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y);
        }

        void Form1_Load(object sender, EventArgs e)
        {
            foreach (PropertyInfo info in typeof(Brushes).GetProperties())
            {
                listBox1.Items.Add(info.Name);
            }
        }
    }
Advertisements

June 26, 2011 - Posted by | Winforms

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: