Make an owner-drawn ListBox that displays pictures in C#

The example Make an owner-drawn ListBox in C# shows how to make an owner-drawn ListBox that display text across multiple lines. This example shows how to display images, too.

The program uses the Planet class to represent information the planets.
class Planet
{
public string Name = "";
public string Stats = "";
public Image Picture = null;

public Planet(string name, Image picture, string stats)
{
Name = name;
Stats = stats;
Picture = picture;
}
}

When the program starts, it adds Planet objects to the ListBox. Because these are objects without a good ToString method, the ListBox cannot reasonably display them by itself so this must be an owner-drawn ListBox.

See the previous example for the basics. This example uses the following MeasureItem event handler to allocate room to draw each entry 100 pixels tall (plus a margin).

private const int ItemMargin = 5;
private const float PictureHeight = 100f;

// Return enough space for the item.
private void lstPlanets_MeasureItem(object sender, MeasureItemEventArgs e)
{
e.ItemHeight = (int)(PictureHeight + 2 * ItemMargin);
}

The following code shows how the program draws the ListBox items.

// Draw the item.
private void lstPlanets_DrawItem(object sender, DrawItemEventArgs e)
{
// Get the ListBox and the item.
ListBox lst = sender as ListBox;
Planet planet = (Planet)lst.Items[e.Index];

// Draw the background.
e.DrawBackground();

// Draw the picture.
float scale = PictureHeight / planet.Picture.Height;
RectangleF source_rect = new RectangleF(
0, 0, planet.Picture.Width, planet.Picture.Height);
float picture_width = scale * planet.Picture.Width;
RectangleF dest_rect = new RectangleF(
e.Bounds.Left + ItemMargin, e.Bounds.Top + ItemMargin,
picture_width, PictureHeight);
e.Graphics.DrawImage(planet.Picture, dest_rect, source_rect, GraphicsUnit.Pixel);

// See if the item is selected.
Brush br;
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
br = SystemBrushes.HighlightText;
else
br = new SolidBrush(e.ForeColor);

// Find the area in which to put the text.
float x = e.Bounds.Left + picture_width + 3 * ItemMargin;
float y = e.Bounds.Top + ItemMargin;
float width = e.Bounds.Right - ItemMargin - x;
float height = e.Bounds.Bottom - ItemMargin - y;
RectangleF layout_rect = new RectangleF(x, y, width, height);

// Draw the text.
string txt = planet.Name + '\n' + planet.Stats;
e.Graphics.DrawString(txt, this.Font, br, layout_rect);

// Outline the text.
e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(layout_rect));

// Draw the focus rectangle if appropriate.
e.DrawFocusRectangle();
}

The code first gets the ListBox and the item that it will be drawing. Remember that item is a Planet object. The program then draws the background.

Next the code figures out how it must scale the planet's picture to make it PictureHeight tall. It makes source and destination rectangles for the picture and uses them to draw it.

The program then picks a brush to use while drawing text. If the ListBox item is selected, the program uses the standard HighlightText colored brush. If the item is not selected, the program uses a brush with the item's foreground color.

The code next makes a RectangleF that defines the area in which text will be drawn. This is the area available to draw in to the right of the planet's picture.

Finally the program draws the text. It finishes by drawing the rectangle showing the area the text is in to make it stand out.

  

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.