Colabora
 

ComboBox Personalizado

[ComboBox con altura variable y color de borde personalizado]

 

Fecha: 12/Ago/2010 (30-07-10)
Autor: José Luis Cabedo - jlcabedo@laplatera.es

 


Introducción

ComboBox con apariencia personalizada, posibilidad de modificar la altura, el color del borde y la flecha del desplegable.

 

Contenido

Como me he aprovechado bastantes veces del código publicado en el sitio del Guille, y viendo bastante cantidad de gente preguntando por este tema, me daría verguenza no compartir con vosotros este código que personaliza la apariencia del ComboBox.

El código es bastante sencillo y no necesita mucha explicación. Simplemante he creado una clase heredada de ComboBox añadiendo el código necesario para modificar la altura, el color del borde y el color y la apariencia de la flecha del desplegable.

En este ejemplo sólo se modifican estas propiedades porque eran las que necesitaba para mi aplicación, no obstante, el ejemplo puede servir para modificar otras propiedades, o la apariencia de otros controles con propiedades bloqueadas.

En este caso, sólo se modificará la apariencia del control si la propiedad FlatStyle está en Standar. Las propiedades que utilizo son las siguientes:

ArrowColor: Color de la flechita del desplagable.
ArrowPersonalized: Nos indica si queremos o no personalizar la flecha.
ArrowStyle: Indica el estilo de la flecha (3D o plana).

BorderColor: Color del borde del control.

SizeHeight: Altura del control (en píxeles).

Nota:
Repito, para que quede claro. En este ejemplo, para que tengan efecto los cambios en estas propiedades, la propiedad FlatStyle ha de tener el valor de Standar.

 

El código:

Imports System.ComponentModel
Imports System.ComponentModel.Design

Public Class clsComboBox
    Inherits ComboBox

    'Envía lso mensajes para que el método WndProc los procese 
    Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal IPtr As IntPtr, _
    ByVal Msg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32
    Private Const CB_SIH As Int32 = &H153

    'Enumeramos los valores que podrá tener la propiedad ArrowStyle
    Public Enum enumArrowStyle
        Arrow3D = 0
        ArrowFlat = 1
    End Enum

    Dim varCArrowColor As Color = Color.FromArgb(255, 74, 97, 132)
    Dim varCArrowPersonalized As Boolean = False
    Dim varCArrowStyle As enumArrowStyle = enumArrowStyle.Arrow3D
    Dim varCBorderColor As Color = System.Drawing.SystemColors.GradientActiveCaption
    Dim varCSizeHeight As Integer = 21

    <Description("Define el color de la flecha del desplegable cuando la propiedad " & _
    "ArrowPersonalized tiene el valor de 'true'."), Category("Apariencia")> _
    Public Property ArrowColor() As Color
        Get
            Return varCArrowColor
        End Get
        Set(ByVal value As Color)
            varCArrowColor = value
            Me.Invalidate()
        End Set
    End Property

    <Description("Indica si queremos que la flecha del desplegable tenga el " & _
    "color personalizado que indicaremos en la propiedad ArrowColor."), _
    Category("Apariencia")> _
    Public Property ArrowPersonalized() As Boolean
        Get
            Return varCArrowPersonalized
        End Get
        Set(ByVal value As Boolean)
            varCArrowPersonalized = value
            Me.Invalidate()
        End Set
    End Property

    <Description("Define el estilo de la flecha del desplegable cuando la propiedad " & _
    "ArrowPersonalized tiene el valor de 'true'."), Category("Apariencia")> _
    Public Property ArrowStyle() As enumArrowStyle
        Get
            Return varCArrowStyle
        End Get
        Set(ByVal value As enumArrowStyle)
            varCArrowStyle = value
            Me.Invalidate()
        End Set
    End Property

    <Description("Color del borde del control cuando la propiedad FlatStyle " & _
    "tenga el valor de 'Standard'."), Category("Apariencia")> _
    Public Property BorderColor() As Color
        Get
            Return varCBorderColor
        End Get
        Set(ByVal value As Color)
            varCBorderColor = value
            Me.Invalidate()
        End Set
    End Property

    <Description("Alto del control en píxeles."), Category("Diseño")> _
    Public Property SizeHeight() As Integer
        Get
            If varCSizeHeight < 6 Then
                varCSizeHeight = 6
            End If
            Return varCSizeHeight
            subSComboBoxHeight(Me, varCSizeHeight)
        End Get
        Set(ByVal value As Integer)
            If value < 6 Then
                value = 6
            End If
            varCSizeHeight = value
            subSComboBoxHeight(Me, value)
        End Set
    End Property

    'El siguente método se utiliza para modificar el alto del control
    Private Sub subSComboBoxHeight(ByVal ctlComboBox As ComboBox, _
    ByVal Height As Int32)
        SendMessage(ctlComboBox.Handle, CB_SIH, -1, Height - 6)
        Me.Refresh()
    End Sub

    'En el método Resize añadimos el código para que el control sólo se pueda modificar
    'desde la propiedad SizeHeight. Si no utilizamos este código, cada vez que cambiamos
    'el tamaño del control manualmente o desde las propiedades Width y Hei el control
    'vuelve a su altura predeterminada
    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        MyBase.OnResize(e)
        If Not Me.Height = varCSizeHeight Then
            subSComboBoxHeight(Me, varCSizeHeight)
        End If
    End Sub

    Protected Overrides Sub WndProc(ByRef Mssg As Message)
        MyBase.WndProc(Mssg)

        If Mssg.Msg = &HF And Me.FlatStyle = Windows.Forms.FlatStyle.Standard Then
            Dim varSPen As Pen = New Pen(varCBorderColor, 1)
            Dim varSRectangle As New Rectangle(0, 0, Me.Width - 1, Me.Height - 1)
            Dim varSe As New PaintEventArgs(Me.CreateGraphics, varSRectangle)

            'Creamos el borde del control, antes hemos definido un pen del color de
            'la propiedad BorderColor y con el tamaño de 1 pixel.
            'Se podría también variabilizar el tamaño del borde del control.
            'También hemos definido un rectángulo del tamaño exacto del control.
            '¡OJO!, si se varibiliza el borde se tendrían que cambiar los datos en
            'el constructor del rectángulo que quedaría de la siguiente forma:
            '(int(Borde/2), int(Borde/2), Me.Width - Borde, Me.Height - Borde)
            varSe.Graphics.DrawRectangle(varSPen, varSRectangle)

            varSPen.Dispose()
            varSRectangle = Nothing

            'Con este código dibujaremos la flechita del desplegable según el valor
            'de las propiedades ArrowColor y ArrowStyle.
            If varCArrowPersonalized Then
                Dim varSWidthIni = Me.Width - 14
                Dim varSHeightIni = Int((Me.Height - 6) / 2) + 1
                If Me.Height / 2 = Int(Me.Height / 2) Then
                    varSHeightIni = varSHeightIni - 1
                End If
                Dim varSpoint1 As Point
                Dim varSpoint2 As Point
                Dim varSpoint3 As Point
                Dim varSpoint4 As Point
                Dim varSpoint5 As Point
                Dim varSpoint6 As Point
                If varCArrowStyle = enumArrowStyle.Arrow3D Then
                    varSpoint1 = New Point(varSWidthIni, varSHeightIni + 1)
                    varSpoint2 = New Point(varSWidthIni + 1, varSHeightIni)
                    varSpoint3 = New Point(varSWidthIni + 4, varSHeightIni + 3)
                    varSpoint4 = New Point(varSWidthIni + 7, varSHeightIni)
                    varSpoint5 = New Point(varSWidthIni + 8, varSHeightIni + 1)
                    varSpoint6 = New Point(varSWidthIni + 4, varSHeightIni + 5)
                Else
                    varSpoint1 = New Point(varSWidthIni, varSHeightIni + 1)
                    varSpoint2 = New Point(varSWidthIni + 1, varSHeightIni - 1)
                    varSpoint3 = New Point(varSWidthIni + 4, varSHeightIni + 3)
                    varSpoint4 = New Point(varSWidthIni + 7, varSHeightIni - 1)
                    varSpoint5 = New Point(varSWidthIni + 9, varSHeightIni + 1)
                    varSpoint6 = New Point(varSWidthIni + 4, varSHeightIni + 6)
                End If
                Dim varSPoint() As Point = {varSpoint1, varSpoint2, _
                varSpoint3, varSpoint4, varSpoint5, varSpoint6}

                varSe.Graphics.FillPolygon(New SolidBrush(varCArrowColor), varSPoint)
                varSPoint = Nothing
            End If
            varSe.Dispose()
        End If
    End Sub
End Class

 


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

System.ComponentModel
System.ComponentModel.Design

 



Compromiso del autor del artículo con el sitio del Guille:

Lo comentado en este artículo está probado (y funciona) con la siguiente configuración:

El autor se compromete personalmente de que lo expuesto en este artículo es cierto y lo ha comprobado usando la configuración indicada anteriormente.

En cualquier caso, el Guille no se responsabiliza del contenido de este artículo.

Si encuentras alguna errata o fallo en algún link (enlace), por favor comunícalo usando este link:

Gracias.


Ir al índice principal de el Guille