Colaboraciones en el Guille

Controles Personalizados III

Control ComboImageBox a Partir de un ComboBox

 

Fecha: 20/May/2006 (19-05-06)
Autor: Nelson Cabezas - [email protected]

Introducción

Continuando con la serie de artículos de controles personalizados, en esta ocasión veremos como crear un ControlBox que soporte el uso de imágenes (Ver figura Nº01).


Figura Nº01: "Uso Control Personalizado ComboImageBox"

En este articulo veremos como crear la librería personalizada y luego como usarla. Se hará referencia "Controles Personalizados I", por lo que se recomienda una lectura.

 

1. Generar Librería Personalizada

- Crear un Proyecto Librería de Clases "ComboImageBox".
- Borrar el Contenido dentro de Class1.vb
- Agregar Las siguientes Referencias: System.Windows.Form y System.Drawing.
- Cambiar el Nombre de Class1.vb a ComboImageBox.vb en el Explorador de Soluciones.
(*) Referencia Visual "Controles Personalizados I"

La idea para crear este control es que el usuario pueda ir agregando ítems al "ComboImageBox", indicando para cada uno de estos: el texto, color del texto, imagen y color de fondo del rectángulo (Ver figura Nº02).


Figura Nº02: "Apariencia de un Elemento del ComboImageBox"

Además Indicar el tipo de letra a usar y un listado de imágenes asociadas. Para explicar como funciona he separado en 5 áreas el código (Ver figura Nº03).


Figura Nº03: "Áreas del Código"

Estas 5 áreas están contenidas dentro de la clase Publica ComboImageBox que a su vez esta contenida en el espacio del mismo nombre. La descripción de las 5 áreas es la siguiente:

1. Declaración de Variables ( Privadas , Publicas )
Privadas:
- ListPicture : Usada para almacenar el ImageList que cargara el usuario.
- BrushFont,BrushBack : usadas para el trabajo de utilizar los colores en el dibujo.
Publicas:
- ComboFont : Almacena el tipo de letra a usar, se carga una sola vez en las caracteristicas del control.
- ComboItemText() : Array donde se almacena el texto de cada ítem.
- ComboItemIcon() : Array donde se almacena el index de la imagen (del ImageList cargado) asociado a cada ítem.
- ComboBackBrushes() : Array donde se almacenan los colores para pintar el rectángulo de fondo de cada ítem.
- ComboFontBrushes() : Array donde se almacenan los colores para el texto de cada ítem.
- ini : variable que indica el index temporal de cada ítem cargado.

2. Propiedad Publica ( ImageList )
A través de una propiedad pública se carga el ImageList a usar en el ComboBox, por lo que este evento se puede hacer desde las propiedades del "ComboImageBox" o en la programación del código.

3. Función ( ComboAddItem(p1,p2,p3,p4) )
Cada vez que sea llamada, se deberá ingresar 4 parámetros que son característicos para definir un ítem del ComboImageBox, los cuales son: Texto, Color del Texto, Index de la Imagen en ImageList y Color del Rectángulo de Fondo. Cuando se reciben estos datos, se aumenta en 1 el total de ítems contenidos, se redimensionan los array y se almacenan los datos en los array respectivos. Finalmente se llama a la función load().

4. Función ( Load() )
Limpia los ítems para agregar de nuevo todos (podría ser que fuera agregando uno a uno, pero opte por este método), desde el array de texto.

5. SubRutina de Dibujo (Evento DrawItem, Evento MeasureItem)
Cada vez que se se llame a dibujar el ComboImagenBox, recurrira a estos dos eventos.
Evento DrawItem
el e.Index nos indica sobre que elemento se esta trabajando, con este dato generamos los brushes para el color de las letras y del rectángulo (variables BrushFont,BrushBack que leen desde los Array de Colores ComboFontBrushes() y ComboBackBrushes() ). Calculamos el alto y ancho de la imagen. Dibujamos el rectángulo (usamos el color desde el array ComboBackBrushes() ). Dibujamos el texto (usamos el texto desde el array ComboItemText() , el tipo de letra con la variable publica ComboFont, el color de la letra con la variable BrushFont) y finalmente dibujamos la imagen ( usamos ListPicture ).
Evento MeasureItem
El evento MeasureItem permite indicar el tamaño de un elemento antes de que se produzca el evento DrawItem de ese elemento.

A continuación sigue código en Visual Basic.NET:

Imports System
Imports System.Windows.Forms
Imports System.Drawing
Namespace ComboImageBox
Public Class ComboImageBox
Inherits ComboBox Private ListPicture As New ImageList
Private BrushFont As SolidBrush
Private BrushBack As SolidBrush Public ComboFont As Font Public ComboItemText() As String Public ComboItemIcon() As Integer Public ComboBackBrushes() As Color Public ComboFontBrushes() As Color Public ini As Integer = -1 Public Property ImageList() As ImageList Get Return ListPicture End Get Set(ByVal ListaImagem As ImageList) ListPicture = ListaImagem End Set End Property Public Function ComboAddItem(ByVal ItemCombo As String, _ ByVal ItemColor As Color, _ ByVal ItemIcono As Integer, _ ByVal ItemColorFondo As Color) As Boolean ini = ini + 1 ReDim Preserve ComboItemText(ini) ReDim Preserve ComboFontBrushes(ini) ReDim Preserve ComboItemIcon(ini) ReDim Preserve ComboBackBrushes(ini) ComboItemText(ini) = ItemCombo ComboFontBrushes(ini) = ItemColor ComboItemIcon(ini) = ItemIcono ComboBackBrushes(ini) = ItemColorFondo load()
End Function Private Sub load() On Error GoTo salir MyBase.Items.Clear() MyBase.Items.AddRange(ComboItemText) MyBase.DropDownStyle = ComboBoxStyle.DropDownList MyBase.DrawMode = DrawMode.OwnerDrawVariable MyBase.ItemHeight = ListPicture.ImageSize.Height MyBase.MaxDropDownItems = ini + 1 MyBase.SelectedIndex = 0 salir: MyBase.Text = "Debe Cargar ImageList" End Sub Private Sub ComboBox_DrawItem(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles MyBase.DrawItem If e.Index <> -1 Then BrushFont = New SolidBrush(ComboFontBrushes(e.Index)) BrushBack = New SolidBrush(ComboBackBrushes(e.Index)) Dim ancho As Integer = Me.ListPicture.Images(ComboItemIcon(e.Index)).Width Dim alto As Integer = Me.ListPicture.Images(ComboItemIcon(e.Index)).Height e.Graphics.FillRectangle(BrushBack, e.Bounds) e.Graphics.DrawString(ComboItemText(e.Index), ComboFont, BrushFont, _ e.Bounds.Left + ancho + 2, _ e.Bounds.Top + alto / 4) e.Graphics.DrawImage(Me.ListPicture.Images(ComboItemIcon(e.Index)), _ e.Bounds.Left, e.Bounds.Top) End If End Sub Private Sub ComboBox_MeasureItem(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MeasureItemEventArgs) Handles MyBase.MeasureItem e.ItemHeight = Me.ListPicture.ImageSize.Height e.ItemWidth = Me.ListPicture.ImageSize.Width End Sub End Class End Namespace

 

Bien hasta acá tenemos lista la librería solo nos queda construir la solución (build solution) y en nuestra carpeta bin quedara un archivo ComboImageBox.dll, el cual debemos copiar y guardar para usar en nuestros proyectos.

 

2. Incluir Nuestra Librería Personalizada ComboImageBox en nuestros Proyectos (*)

Primero creamos un nuevo proyecto (para probar nuestro control) o abrimos un proyecto donde queramos incluir el control personalizado.

- Seleccionamos agregar un nuevo ítem al ToolBox.
- Buscamos y Seleccionamos el archivo ComboImageBox.dll
- Aceptamos y ya nos quedara en el ToolBox el Control ComboImagenBox (Ver figura Nº04).
(*) Referencia Visual "Controles Personalizados I"


Figura Nº04: "ToolBox Personalizado"


3. Usar ComboImageBox

Primero creamos un nuevo proyecto (para probar nuestro control) o abrimos un proyecto donde queramos incluir el control personalizado.
- Creamos una lista de imágenes (ImageList).
- Seleccionamos ComBoImageBox desde el ToolBox y lo arrastramos a la pantalla de diseño.
- Seleccionamos en las propiedades del ComboImageBox y agregamos la ImageList a utilizar (Ver figura Nº05).


Figura Nº05: "Agregar ComboImageBox, a una aplicación"

Luego dentro del código definir el tipo de letra, el control no trae ninguno por defecto por lo que es necesario definirlo. Finalmente ir agregando los ítem dentro del ComboImageBox, con la función "ComboAddItem", dentro de la cual van los parámentros:
- Texto.
- Color de la letra.
- Index de la imagen guardada en la ImageList.
- Color de Fondo del Rectángulo donde aparecerá el ítem.

A continuación sigue código en Visual Basic.NET:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

  

  

  

   Me.ComboImageBox1.ComboFont = New Font("Verdana", 8, FontStyle.Bold)

         With Me.ComboImageBox1
      .ComboAddItem("Urdidores", Color.Red, 0, Color.Yellow)
      .ComboAddItem("Hilandera", Color.Black, 1, Color.White)
      .ComboAddItem("Telares", Color.Green, 2, Color.LightGray)
      .ComboAddItem("Secadora", Color.DarkGreen, 3, Color.LightSalmon)
      .ComboAddItem("Apresto", Color.Blue, 4, Color.LimeGreen)
  
  
  
   End With
End Sub

 

4. Observaciones

- También se puede incluir la ImageList desde el código con Me.ComboImageBox1.ImageList= .....
- Las imágenes se pueden repetir las veces que quieran al agregar nuevos ítem o mezclar como sea el gusto.
- Si se equivocan y por ejemplo el máximo index del ImageList es 4 y agregan un 5, la aplicación se cae.
- Si no hay una ImageList agregada al ComboImageBox, la aplicación se cae.
- El tamaño de los imagenes viene dado por la ImageList.
- El alto del ComboImageBox es el alto de la ImageList.

 


Espacios de nombres usados en el código de este artículo:

Imports System
Imports System.Windows.Forms
Imports System.Drawing


Fichero con la DLL : nelsonc_ComboImageBox_dll.zip - 3,18 KB
(MD5 checksum: 45F08B06250444B1E80371F948172BDE)

Fichero con el Código: nelsonc_ComboImageBox_src.zip - 17,0 KB
(MD5 checksum: D4981C953B54F51BA207F15F9444DBD2)

Fichero con DLL Aplicada : nelsonc_ComboImageBox_dem.zip - 75,5 KB
(MD5 checksum: 8432CC8804F62E6A0058DBD590D76436)


ir al índice principal del Guille