jueves, 25 de junio de 2015

Windows Forms. ComboBox con imágenes

ComboBox con imágenesEn este artículo voy a mostrar cómo crear un CombBox en el que cada item cuente con una imagen además del texto.











Para mostrar el ejemplo voy a crear un nuevo proyecto de Windows Forms llamado ComboBoxImage.

Proyecto ComboBoxImage


En el formulario Form1 que se crea por defecto he añadido un control PictureBox picImage, un ComboBox cmbImages y un control ImageList listImages.

Al control ImageList le he añadido ocho imágenes (de minions ahora que están tan de moda).

Formulario de prueba


En el constructor del formulario establezco la propiedad DropDownStyle del ComboBox a ComboBoxStyle.DropDownList y la propiedad DrawMode a DrawMode.OwnerDrawFixed para poder personalizar el proceso de dibujado de los items.

También le añado 8 items con cadenas vacías al control ComboBox (uno por cada imagen del control ImageList).

public Form1()
{
 InitializeComponent();
 cmbImages.DropDownStyle = ComboBoxStyle.DropDownList;
 cmbImages.DrawMode = DrawMode.OwnerDrawFixed;
 cmbImages.Items.AddRange(
  Enumerable.Repeat<string>("", listImages.Images.Count).ToArray());
}
Public Sub New()

 InitializeComponent()

 cmbImages.DropDownStyle = ComboBoxStyle.DropDownList
 cmbImages.DrawMode = DrawMode.OwnerDrawFixed
 cmbImages.Items.AddRange( _
  Enumerable.Repeat(Of String)("", listImages.Images.Count).ToArray())

End Sub



En el evento DrawItem del ComboBox dibujaremos cada uno de los elementos.
A través de los métodos DrawBackground y DrawFocusRectangle del objeto DrawItemEventArgs dibujamos el fondo del elemento y el rectángulo para resaltar el elemento seleccionado, si lo está.
A continuación dibujo utilizando el objeto Grapics del DrawItemEventArgs la imagen correspondiente al item a dibujar (identificado por la propiedad Index de DrawItemEventArgs) y un texto.
Redimensiono las imágenes antes de dibujarlas a un tamaño de 32x32, de otra forma se dibujarían las imágenes en su tamaño original.

private void cmbImages_DrawItem(object sender, DrawItemEventArgs e)
{
 e.DrawBackground();
 e.DrawFocusRectangle();
 if (e.Index >= 0)
 {
  if (e.Index < listImages.Images.Count)
  {
   Image img = new Bitmap(listImages.Images[e.Index], new Size(32, 32));
   e.Graphics.DrawImage(img, new PointF(e.Bounds.Left, e.Bounds.Top));
  }
  e.Graphics.DrawString(string.Format("Minion {0}", e.Index + 1)
   , e.Font, new SolidBrush(e.ForeColor)
   , e.Bounds.Left + 32, e.Bounds.Top);
 }
}
Private Sub cmbImages_DrawItem(sender As Object, e As DrawItemEventArgs) Handles cmbImages.DrawItem
 e.DrawBackground()
 e.DrawFocusRectangle()
 If e.Index >= 0 Then
  If e.Index < listImages.Images.Count Then
   Dim img As Image = New Bitmap(listImages.Images(e.Index), New Size(32, 32))
   e.Graphics.DrawImage(img, New PointF(e.Bounds.Left, e.Bounds.Top))
  End If
  e.Graphics.DrawString(String.Format("Minion {0}", e.Index + 1) _
          , e.Font, New SolidBrush(e.ForeColor) _
          , e.Bounds.Left + 32, e.Bounds.Top)
 End If
End Sub

Aunque con esto ya tendríamos listo el ComboBox con las imágenes voy a realizar una última modificación haciendo que en el evento SelectedIndexChanged del ComboBox se cargue en el PictureBox la imagen seleccionada.

private void cmbImages_SelectedIndexChanged(object sender, EventArgs e)
{
 ComboBox combo = (ComboBox)sender;
 if (combo.SelectedIndex >= 0)
  picImage.Image = listImages.Images[combo.SelectedIndex];
 else
  picImage.Image = null;
}
Private Sub cmbImages_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbImages.SelectedIndexChanged
 Dim combo As ComboBox = CType(sender, ComboBox)
 If combo.SelectedIndex >= 0 Then
  picImage.Image = listImages.Images(combo.SelectedIndex)
 Else
  picImage.Image = Nothing
 End If
End Sub

Ahora ya podemos arrancar la aplicación y comprobar el funcionamiento del ComboBox.

Resultado final

El código

Puedes descargar el código de ejemplo de:


6 comentarios:

  1. Hola Píldoras, me parecen muy interesantes tus artículos. ¿Sería posible que más adelante cuando tengas tiempo puedas subir algo sobre Búsquedas y autocompletado en Windows Form?

    ResponderEliminar
  2. Hola Manuel, no sé si has visto los artículos que publiqué sobre la creación de un control con sugerencias de búsqueda:
    http://pildorasdotnet.blogspot.com.es/2015/05/textbox-sugerencias-windows-forms.html

    ResponderEliminar
  3. Como seria para que muestre el nombre de la imagen, y no se genere un preestablecido?
    Ej; Dos imagenes, la 1 se llama "Cable.png", y se muestre en el combobox como "Cable", la 2 se llama "Pan.png" y se muestre como "Pan".

    Saludos, gracias de antemano.

    ResponderEliminar
    Respuestas
    1. Deberías cambiar la instrucción e.Graphics.DrawString para mostrar el texto que deseas. El texto podrías sacarlo de la imagen del ImageList o añadir los textos como items del ComboBox.
      En el ejemplo yo añado por cada imagen una cadena vacía:
      cmbImages.Items.AddRange(
      Enumerable.Repeat("", listImages.Images.Count).ToArray());
      Pero podrías añadir una cadena diferente para cada elemento y mostrarla en el evento DrawItem.

      Eliminar
  4. No se ven las imagenes correctamente a que se debe

    ResponderEliminar
  5. Hola Manuel,
    he probado ha descargarme el proyecto de ejemplo y, al arrancarlo, me muestra las imágenes sin ningún problema. ¿Podrías concretar más tu problema?

    ResponderEliminar