Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

How to Display Images in ComboBox in 5 Minutes?

4.86/5 (20 votes)
1 Sep 2010CPOL2 min read 143.1K   8.9K  
This is an extended ComboBox which supports images for items

Introduction

This is a simple ComboBox that displays images to the user. I saw many other solutions, most of which are complex and override most ComboBox class properties and the draw methods which may cause a lot of problems.

This is a very simple method to add images in the ComboBoxes.

Fig1.png

Fig 1

How to Use?

Copy the ImagedComoBox.exe from the project path bin\Release to your project directory. In Visual Studio, open the Solution Explorer, right click the project name, and choose Add Reference. Click Browse button, locate the ImagedComoBox.exe and select it. To display the control in Toolbox, right click on the toolbox, click Add/Remove Items. From the Customize Toolbox window, select the ImagedComoBox.exe.

Drag the ImagedComboBox from the Toolbox and drop it in your form as shown in Fig 2.

<shape id="_x0000_i1026" style="WIDTH: 623.25pt; HEIGHT: 375pt" type="#_x0000_t75" alt="Fig2.png">

Fig2.png

Fig 2. Drag and drop the control

Using the Code

The constructor:

  • Sets the ComboBoxStyle to DropDownList. You can change it as you need.
  • Sets owner draw mode
  • Subscribes the DrawItem event
C#
public ImagedComboBox()
{
//Specifies that the list is displayed by clicking the down arrow 
//and that the text portion is not editable. 
//This means that the user cannot enter a new value. 
//Only values already in the list can be selected. The list displays only if 
DropDownStyle = ComboBoxStyle.DropDownList; 
//All the elements in the control are drawn manually and can differ in size.
DrawMode = DrawMode.OwnerDrawVariable;
//using DrawItem event we need to draw item
DrawItem += ComboBoxDrawItemEvent;
}

In the ComboBoxDrawItemEvent: I draw the item content and the image.

I'm drawing the item background within the bounds specified in the Overload:System.Windows.Forms.DrawItemEventArgs.

C#
e.DrawBackground();

I'm drawing the item image at the specified location and with the specified size.

C#
e.Graphics.DrawImage(comboboxItem.Image, e.Bounds.X, 
			e.Bounds.Y, ItemHeight, ItemHeight); 

Parameters

  • comboBox.image: Item Image, given with the item.
  • e.BoundsX: The-coordinate of the upper-left corner of the item image to draw.
  • e.Bounds.Y: The y-coordinate of the upper-left corner of the item image to draw.
  • ItemHeight: Width of the item image to draw.
  • ItemHeight: Height of the item image to draw.
    You can also scale the image to the rectangle if you want to just use the property.
  • destRect: System.Drawing.Rectangle structure that specifies the location and size of the drawn image.

After that, I draw the item text string in the calculated rectangle with the specified System.Drawing.Brush and System.Drawing.Font objects.

C#
//we need to draw the item as string because we made drawmode to ownervariable
e.Graphics.DrawString(Items[e.Index].Value.ToString(), Font, Brushes.Black,
new RectangleF(e.Bounds.X + ItemHeight, e.Bounds.Y, DropDownWidth, ItemHeight)); 

Parameters

  • Items[e.Index]: Selected item
  • font: System.Drawing.Font that defines the text format of the string
  • brush: System.Drawing.Brush that determines the color and texture of the drawn text
  • layoutRectangle: System.Drawing.RectangleF structure that specifies the location of the drawn

The size of the layoutRectangle is:

C#
x = ComboBox top left x.
x= ComboBox top left y.
Width = Iterate through all items in Combobox and get MaxWidth.
Height = item height.
/// </summary>
/// Draws overridden items.
/// <param name="sender"></param> 
/// <param name="e"></param> 
private void ComboBoxDrawItemEvent(object sender, DrawItemEventArgs e) 
{ 
   //Draw background of the item e.DrawBackground(); 
   if (e.Index != -1)
   { 
     // selected item 
     var comboboxItem = Items[e.Index];
     //Draw the image in combo box using its bound and ItemHeight 
     e.Graphics.DrawImage(comboboxItem.Image, 
		e.Bounds.X, e.Bounds.Y, ItemHeight, ItemHeight); 
     //we need to draw the item as string because we made drawmode to ownervariable
     e.Graphics.DrawString(Items[e.Index].Value.ToString(), Font, 
	Brushes.Black, new RectangleF(e.Bounds.X + ItemHeight, e.Bounds.Y, 
	DropDownWidth, temHeight));
    }
   //draw rectangle over the item selected 
   e.DrawFocusRectangle(); 
} 

The ComboBox_MeasureItem method measures the item.ToString() width, the width is important to fit the item text inside the draw rectangle.

How Does It Work?

  • Sets the MaxWidth initialize value to ImagedCombobox.Width
  • Iterates through all items in the ImagedCombobox to find the new max width
  • Checks the item.ToString() measured width greater than the maxWidth
    C#
    g.MeasureString(item.ToString(), Font).width).Where(width=> width> maxWidth))  
  • If greater, sets the ComboBoxItem.Width to maxWidth and adds the offset
    C#
    maxWidth = width;  
    DropDownWidth = maxWidth + 20; 

Parameters

  • item.ToString(): String to measure (ComboBoxItem)
  • font: System.Drawing.Font that defines the text format of the string
  • width: Maximum width of the string
C#
/// <summary>
/// I have set the Draw property to DrawMode.OwnerDrawVariable, 
/// so I must calculate the item measurement. 
/// I will set the height and width of each item before it is drawn. 
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ComboBox1_MeasureItem(object sender, MeasureItemEventArgs e)
{
  var g = CreateGraphics();
  var maxWidth = 0;
  foreach (var width in Items.ItemsBase.Cast<object>().Select(element => 
  (int)g.MeasureString(element.ToString(), Font).Width).Where(width => width > maxWidth))
  {
    maxWidth = width;
  }
  DropDownWidth = maxWidth + 20;
}  

Important Classes

  • ComboBoxItem: This class represents an ImagedComboBox item which may contain an image and value.
  • ComboCollection: Collections of ComboBoxItem

History

  • 1st September, 2010: Initial post

License

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