Here's a custom control that automatically handles displaying colors in a ComboBox. My goal is to have it be flexible (Automatically include system colors, or an array of user selected colors) and I'd like other people to test it out.
Here's a reference thread on where this thing started: http://www.vbdotnetforums.com/component-development/28782-color-combobox.html
VB.NET:
Option Explicit On
Option Strict On
Imports System.ComponentModel
Public Class ColorComboBox
Inherits ComboBox
Private _ColorList As List(Of Color)
Private _SortAlphabetical As Boolean
Private _IncludeTransparent As Boolean
Private _IncludeSystemColors As Boolean
Private _MinimumSize As New Size(60I, 21I)
#Region " Constructors "
Public Sub New()
Call PreInitialize()
Call Initialize()
End Sub
Public Sub New(ByVal IncludeTransparent As Boolean, ByVal IncludeSystemColors As Boolean, ByVal Alphabetical As Boolean)
_IncludeTransparent = IncludeTransparent
_IncludeSystemColors = IncludeSystemColors
_SortAlphabetical = Alphabetical
Call PreInitialize()
Call Initialize()
End Sub
Public Sub New(ByVal TheColors() As Color)
Call PreInitialize()
_ColorList.AddRange(TheColors)
Call SetValues()
End Sub
#End Region
#Region " Properties "
<Description("Sort the colors in the DropDown alphabetically"), DefaultValue(False), Category("Colors")> _
Public Property SortAlphabetically() As Boolean
Get
Return _SortAlphabetical
End Get
Set(ByVal value As Boolean)
If _SortAlphabetical <> value Then
_SortAlphabetical = value
Call SetValues()
End If
End Set
End Property
<Description("Include the transparent color in the DropDown"), DefaultValue(False), Category("Colors")> _
Public Property IncludeTransparent() As Boolean
Get
Return _IncludeTransparent
End Get
Set(ByVal value As Boolean)
If _IncludeTransparent <> value Then
_IncludeTransparent = value
If value = True Then
If _ColorList.Contains(Color.Transparent) = False Then
_ColorList.Add(Color.Transparent)
Call SetValues()
End If
Else
If _ColorList.Contains(Color.Transparent) = True Then
_ColorList.Remove(Color.Transparent)
Call SetValues()
End If
End If
End If
End Set
End Property
<Description("Include the system colors in the DropDown"), DefaultValue(False), Category("Colors")> _
Public Property IncludeSystemColors() As Boolean
Get
Return _IncludeSystemColors
End Get
Set(ByVal value As Boolean)
If _IncludeSystemColors <> value Then
_IncludeSystemColors = value
If value = True Then
Call AddSystemColors()
Else
Call RemoveSystemColors()
End If
End If
End Set
End Property
<Browsable(False), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), _
DefaultValue(False)> _
Public Shadows ReadOnly Property Sorted() As Boolean
Get
Return False
End Get
End Property
<Browsable(False), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), _
DefaultValue(Windows.Forms.DrawMode.OwnerDrawFixed)> _
Public Shadows ReadOnly Property DrawMode() As System.Windows.Forms.DrawMode
Get
Return System.Windows.Forms.DrawMode.OwnerDrawFixed
End Get
End Property
<Browsable(False), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), _
DefaultValue(System.Windows.Forms.ComboBoxStyle.DropDownList)> _
Public Shadows ReadOnly Property DropDownStyle() As System.Windows.Forms.ComboBoxStyle
Get
Return System.Windows.Forms.ComboBoxStyle.DropDownList
End Get
End Property
<Browsable(False), EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), _
DefaultValue("60, 21")> _
Public Shadows ReadOnly Property MinimumSize() As System.Drawing.Size
Get
Return _MinimumSize
End Get
End Property
#End Region
#Region " Methods "
<Description("Add a color to the DropDown")> _
Public Sub Add(ByVal Item As Color)
If _ColorList.Contains(Item) = False Then
_ColorList.Add(Item)
Call SetValues()
End If
End Sub
<Description("Add an array of colors to the DropDown")> _
Public Sub AddRange(ByVal Items() As Color)
For Each clr As Color In Items
If _ColorList.Contains(clr) = False Then _ColorList.Add(clr)
Next clr
Call SetValues()
End Sub
<Description("Removes a color from the DropDown")> _
Public Sub Remove(ByVal Item As Color)
If _ColorList.Contains(Item) = False Then
_ColorList.Remove(Item)
Call SetValues()
End If
End Sub
Public Sub RemoveRange(ByVal Items() As Color)
For Each clr As Color In Items
If _ColorList.Contains(clr) = False Then _ColorList.Remove(clr)
Next clr
Call SetValues()
End Sub
#End Region
#Region " Initialize, SetValues "
Private Sub PreInitialize()
MyBase.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
MyBase.DropDownStyle = ComboBoxStyle.DropDownList
MyBase.Sorted = False
MyBase.MinimumSize = _MinimumSize
_ColorList = New List(Of Color)
End Sub
Private Sub Initialize()
If DesignMode = False Then
Dim CurrColor As Color
_ColorList.Clear()
For Each aColorName As String In System.Enum.GetNames(GetType(System.Drawing.KnownColor))
CurrColor = Color.FromName(aColorName)
If _IncludeSystemColors = True Then
If _IncludeTransparent = True Then
If _ColorList.Contains(CurrColor) = False Then _ColorList.Add(CurrColor)
Else
If CurrColor <> Color.Transparent AndAlso _ColorList.Contains(CurrColor) = False Then _ColorList.Add(CurrColor)
End If
Else
If _IncludeTransparent = True Then
If CurrColor.IsSystemColor = False AndAlso _ColorList.Contains(CurrColor) = False Then _ColorList.Add(CurrColor)
Else
If CurrColor.IsSystemColor = False AndAlso CurrColor <> Color.Transparent AndAlso _ColorList.Contains(CurrColor) = False Then _ColorList.Add(CurrColor)
End If
End If
Next aColorName
Call SetValues()
End If
End Sub
Private Sub SetValues()
Me.Items.Clear()
If DesignMode = False Then
If _SortAlphabetical = False Then
_ColorList.Sort(AddressOf SortColors)
Else
_ColorList.Sort(AddressOf SortAlphabetical)
End If
For Counter As Integer = 0I To _ColorList.Count - 1I
MyBase.Items.Add(_ColorList(Counter))
Next Counter
End If
End Sub
#End Region
#Region " AddSystemColors, RemoveSystemColors "
Private Sub AddSystemColors()
If DesignMode = False Then
Dim CurrColor As Color
For Each aColorName As String In System.Enum.GetNames(GetType(System.Drawing.KnownColor))
CurrColor = Color.FromName(aColorName)
If CurrColor.IsSystemColor = True AndAlso _ColorList.Contains(CurrColor) = False Then _ColorList.Add(CurrColor)
Next aColorName
Call SetValues()
End If
End Sub
Private Sub RemoveSystemColors()
If DesignMode = False Then
For Counter As Integer = _ColorList.Count - 1I To 0I Step -1I
If _ColorList(Counter).IsSystemColor = True Then _ColorList.RemoveAt(Counter)
Next Counter
'For Each clr As Color In _ColorList
' If clr.IsSystemColor = True Then _ColorList.Remove(clr)
'Next clr
Call SetValues()
End If
End Sub
#End Region
#Region " Overrides Sub "
Protected Overrides Sub OnFontChanged(ByVal e As System.EventArgs)
Select Case True
Case Me.Font.SizeInPoints > 12.0F : Me.Font = New Font(Me.Font.FontFamily, 12.0F, Me.Font.Style)
Case Me.Font.SizeInPoints < 8.0F : Me.Font = New Font(Me.Font.FontFamily, 8.0F, Me.Font.Style)
End Select
'If Me.Font.SizeInPoints > 12.0F Then Me.Font = New Font(Me.Font.FontFamily, 12.0F, Me.Font.Style)
End Sub
Protected Overrides Sub onDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
e.DrawBackground()
e.DrawFocusRectangle()
If e.Index >= 0 Then
' Get the Color object from the Items list
Dim aColor As Color = CType(Me.Items(e.Index), Color)
' get a square using the bounds height
Dim rect As Rectangle = New Rectangle(5I, e.Bounds.Top + 2I, e.Bounds.Height - 3I, e.Bounds.Height - 5I)
Dim br As Brush = Brushes.White
' change brush color if item is selected
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
br = Brushes.White
Else
br = Brushes.Black
End If
' draw a rectangle and fill it
e.Graphics.DrawRectangle(New Pen(aColor), rect)
e.Graphics.FillRectangle(New SolidBrush(aColor), rect)
' draw a border
rect.Inflate(1I, 1I)
e.Graphics.DrawRectangle(Pens.Black, rect)
' draw the Color name
e.Graphics.DrawString(aColor.Name, Me.Font, br, e.Bounds.Height + 5I, ((e.Bounds.Height - Me.Font.Height) \ 2I) + e.Bounds.Top)
End If
End Sub
#End Region
#Region " SortColors "
Private Function SortColors(ByVal x As Color, ByVal y As Color) As Integer
Dim huecompare As Integer = x.GetHue.CompareTo(y.GetHue)
Dim satcompare As Integer = x.GetSaturation.CompareTo(y.GetSaturation)
Dim brightcompare As Integer = x.GetBrightness.CompareTo(y.GetBrightness)
Select Case True
Case huecompare <> 0I : Return huecompare
Case satcompare <> 0I : Return satcompare
Case brightcompare <> 0I : Return brightcompare
Case Else : Return 0I
End Select
End Function
Private Function SortAlphabetical(ByVal x As Color, ByVal y As Color) As Integer
Return x.Name.CompareTo(y.Name)
End Function
#End Region
End Class