mercoledì 2 novembre 2011

[VB.NET] Un Color Picker per Known Colors

Descrizione :
Un mio controllo Color Picker tipo ComboBox per la scelta veloce di colori dalla palette dei Known Colors di Visual Studio.

+ Articolo :

Si tratta di una Classe che eredita da ComboBox, e che permette la selezione di un Colore tra i Known Colors di VS, ma escludendo i colori di sistema e il Transparent.
Tra le varie caratteristiche, la Proprietà PickedColor
e l'Evento OnPickedColorChanged(), per rendere ancora più semplice l'uso dal codice esterno.

Inoltre ci sono due modalità di visualizzazione dei colori alternative :

1. Standard alfabetica : l'insieme dei colori disponibili viene ordinato alfabeticamente A-Z.

2. HSB : l'insieme dei colori disponibili viene ordinato in base allo schema H-S-B, ossia Hue --> Saturation --> Brightness.
Faccio notare che questo tipo di ordinamento è lo stesso identico della palette dei Colors sulla scheda Web in qualsiasi selezione di colori del designer di Visual Studio.

E' possibile passare dall'una all'altra semplicemente con la Proprietà OrderByHSB : se False imposta l'ordinamento alfabetico, se True, tramite istanza della Inner Class ColorComparer, imposta l'ordinamento HSB.

--> Classe ColorPickerCombo :

Imports System.ComponentModel

Public Class ColorPickerCombo
    Inherits ComboBox

    Private Class ColorComparer
        Implements IComparer(Of String)

        Public Function Compare(ByVal x As String, ByVal y As String) As Integer Implements IComparer(Of String).Compare

            Dim cx As Color = Color.FromName(x)
            Dim cy As Color = Color.FromName(y)

            If cx.GetHue = cy.GetHue Then
                If cx.GetSaturation = cy.GetSaturation Then
                    Return cx.GetBrightness.CompareTo(cy.GetBrightness)
                Else
                    Return cx.GetSaturation.CompareTo(cy.GetSaturation)
                End If
            Else
                Return cx.GetHue.CompareTo(cy.GetHue)
            End If

        End Function

    End Class

    Private m_colornames As New List(Of String)
    Private m_orderbyhsb As Boolean
    Private m_pickedcolor As Color

    Public Property OrderByHSB As Boolean
        Get
            Return m_orderbyhsb
        End Get
        Set(ByVal value As Boolean)
            m_orderbyhsb = value
            Me.Items.Clear()
            If m_orderbyhsb = True Then
                m_colornames.Sort(New ColorComparer)
            Else
                m_colornames.Sort()
            End If
            Me.Items.AddRange(m_colornames.ToArray)
            If Me.Items.Count > 0 Then Me.SelectedIndex = 0
        End Set
    End Property

    Public Property PickedColor As Color
        Get
            Return m_pickedcolor
        End Get
        Set(ByVal value As Color)
            m_pickedcolor = value
            Me.SelectedItem = m_pickedcolor.ToKnownColor.ToString
            RaiseEvent OnPickedColorChanged()
        End Set
    End Property

    Public Event OnPickedColorChanged()

    Public Sub New()

        If LicenseManager.UsageMode = LicenseUsageMode.Runtime Then

            Me.DrawMode = DrawMode.OwnerDrawFixed
            Me.DropDownStyle = ComboBoxStyle.DropDownList

            Dim KC As Color
            For Each knclr As KnownColor In [Enum].GetValues(GetType(KnownColor))

                KC = Color.FromKnownColor(knclr)

                If Not KC.IsSystemColor And Not KC = Color.Transparent Then

                    m_colornames.Add(KC.ToKnownColor.ToString)

                End If

            Next

        End If

    End Sub

    Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)

        If e.Index < 0 Then Exit Sub

        Dim h As Integer
        Dim BR As New SolidBrush(Color.FromName(Me.Items(e.Index)))

        e.DrawBackground()

        With e.Graphics
            h = .MeasureString(Me.Items(e.Index), Me.Font).Height
            .FillRectangle(BR, e.Bounds.X, e.Bounds.Y, h * 3, h)
            .DrawString(Me.Items(e.Index).ToString(), Me.Font, Brushes.Black, _
                        New RectangleF(e.Bounds.X + h * 3, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height))
        End With

        e.DrawFocusRectangle()

    End Sub

    Protected Overrides Sub OnSelectedIndexChanged(ByVal e As System.EventArgs)

        Me.PickedColor = Color.FromName(Me.SelectedItem)

    End Sub

End Class

--> Form di Test :
Una semplice FormMain per testare il nuovo controllo.
Basterà compilare e aggiungere a FormMain il "ColorPickerCombo1".
Due ulteriori controlli per rendere il test un po' più significativo :
- Una CheckBox : chk_orderbyhsb
- Una ListBox : lst_colortest

--> Codice FormMain :
Public Class FormMain

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

        Dim KC As Color
        For Each knclr As KnownColor In [Enum].GetValues(GetType(KnownColor))
            KC = Color.FromKnownColor(knclr)
            If Not KC.IsSystemColor And Not KC = Color.Transparent Then
                lst_colortest.Items.Add(KC.ToKnownColor.ToString)
            End If
        Next

    End Sub

    Private Sub lst_colortest_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lst_colortest.SelectedIndexChanged
        ColorPickerCombo1.PickedColor = Color.FromName(lst_colortest.SelectedItem.ToString)
    End Sub

    Private Sub ColorPickerCombo1_OnPickedColorChanged() Handles ColorPickerCombo1.OnPickedColorChanged
        lst_colortest.BackColor = ColorPickerCombo1.PickedColor
        lst_colortest.SelectedItem = ColorPickerCombo1.PickedColor.ToKnownColor.ToString
    End Sub

    Private Sub chk_orderbyhsb_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chk_orderbyhsb.CheckedChanged
        If chk_orderbyhsb.CheckState = CheckState.Checked Then
            ColorPickerCombo1.OrderByHSB = True
        Else
            ColorPickerCombo1.OrderByHSB = False
        End If
    End Sub
  
End Class


+ Fine Articolo.


Un Click su "Mi Piace" è il modo migliore per ringraziare l'autore di questo articolo.



0 commenti:

Posta un commento

 
Design by Free WordPress Themes Modificato da MarcoGG