Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ColorPicker - ColorPicker with a compact footprint (VB.NET)

0.00/5 (No votes)
12 Jan 2012 1  
An RGB/HSB color selection control with an eye-dropper and quick swatches.

ColorPickerNoRGB.jpg

Introduction

A color picker... isn't there a bunch of those out there already? Yeah, but none of them were really what I needed. There are some cool ones, but they were either too big, or too limited. Besides, I enjoy the challenge. What I wanted was to be able to easily select a color from a color gradient bar and adjust the brightness and saturation (HSB). Again, already out there, but I wanted a control with a smaller footprint. I didn't want the control taking up most of my form area, and I didn't want to have to open a separate dialog every time. So, here is my version.

Controls in Library

  • gColorPicker
  • gEyeDropper
  • gColorComboBox
  • gEnumBox

ColorPicker Control Features

  • Hue (Color) selection bar
  • Saturation adjustment bar
  • Brightness adjustment bar
  • Alpha (Transparency) adjustment slider
  • RGB - Red, Green, and Blue adjustment track bars (optional)
  • Predefined color swatches fly-out
  • EyeDropper tool to select a color from anywhere on your screen

ColorPickerFeatures.jpg

Events

  • Public Event ColorPicked(ByVal sender As Object, _
           ByVal CurrentColor As Color, ByVal ClosestColorName As String)
  • This event will fire when the color bar is clicked.

  • Public Event ColorChanging(ByVal sender As Object, _
           ByVal CurrentColor As Color, ByVal ClosestColorName As String)
  • This event will fire when the color value is changing.

Init

The class Implements ISupportInitialize.

Then using the code below the ColorChanging event can be blocked in the Value Property during the control's initialization.

Private Sub BeginInit() Implements ISupportInitialize.BeginInit
    Initializing = True
End Sub

Private Sub EndInit() Implements ISupportInitialize.EndInit
    Initializing = False
End Sub

Initialize

Builds the color bars and lays out the control. There are two resources loaded here. First is HideCursor.cur. This is a blank cursor used when the bar selectors are being adjusted so cursor will disappear. The second is the Lizardsml.jpg to tile behind the color bar to show the alpha transparency better. It will load a backup for each if, for some reason, these resources are missing.

Control Properties

Here is a list of the primary properties:

  • Value
  • The current color selected.

  • HideRGB
  • Shows or hides the RGB control box.

  • FlyOut
  • Does the fly-out open on MouseOver or Click? This property is also available from a context-menu at runtime.

Color Helpers

Special thanks to Guillaume Leparmentier for his great article: Manipulating colors in .NET - Part 1 [^]. To convert between RGB and HSB, I used some of his RGB/HSB helper code here, with little modification.

Mouse Events

Track if the cursor is over a bar or over the alpha pointer.

For rectangular areas:

If New Rectangle(ptColor, szColor).Contains(e.Location) Then
    .
    .
    .
End If

For irregular areas (GraphicsPath):

If GetAlphaPath(sngXAlpha).IsVisible(e.Location) Then
    .
    .
    .
End If

Drawing

Contains the routines to draw the bars and the pointers, invalidate selectors, and paint the control.

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaint(e)

    Dim g As Graphics = e.Graphics

    'Draw Color Value
    g.FillRectangle(New TextureBrush(bmpImg, WrapMode.Tile), ValueDisplay)
    g.FillRectangle(New SolidBrush(Color.FromArgb(CInt(nudAlpha.Value), _
        _Value)), ValueDisplay)

    'Draw a rectangle around the ValueDisplay
    g.DrawRectangle(Pens.DarkGray, ValueDisplay.Location.X - 3, _
        ValueDisplay.Location.Y - 3, ValueDisplay.Width + 5, _
        ValueDisplay.Height + 5)

    'Draw the Alpha Pointer
    g.FillPath(New SolidBrush(AlphaColor), GetAlphaPath(sngXAlpha))
    g.DrawPath(Pens.Blue, GetAlphaPath(sngXAlpha))

    'Draw Hue Color Bar
    g.DrawImage(bmpColorBar, ptColorPaint)
    DrawSelector(g, New Rectangle(ptColor, szColor), _
        sngXColor, panHueSwatch.BackColor)

    'Draw Saturation Color Bar
    Using br As LinearGradientBrush = New LinearGradientBrush _
      (New Rectangle(ptSatPaint.X + 3, ptSatPaint.Y + 3, _
      szSat.Width, szSat.Height), _
      Color.White, CurrColor, LinearGradientMode.Horizontal)
        g.FillRectangle(br, New Rectangle( _
            ptSatPaint.X + 3, ptSatPaint.Y + 3, szSat.Width, szSat.Height))
        g.DrawRectangle(Pens.DarkGray, New Rectangle( _
            ptSatPaint.X, ptSatPaint.Y, szSat.Width + 5, szSat.Height + 5))
    End Using

    'DrawSelector
    DrawSelector(g, New Rectangle(ptSat, szSat), sngXSat, _
        HSBtoColor(nudHue.Value, nudSat.Value / 100, 1))

    'Draw Brightness Color Bar
    g.DrawImage(bmpBrightBar, ptBrightPaint)
    DrawSelector(g, New Rectangle(ptBright, szBright), sngXBright, _
        HSBtoColor(0, 0, nudBright.Value / 100))

End Sub

Control Events

Contains the events for the controls on the color picker control.

ColorBox

DrawItem event to take over drawing the combobox items and adding a color sample to each item.

EyeDropper Events

Update the sample and color value based on the EyeDropper control. The EyeDropper has these two events:

  • Public Event SelectedColorChanging(ByVal sender As Object, _
        ByVal CurrColor As Color)
  • Public Event SelectedColorChanged(ByVal sender As Object, _
        ByVal CurrColor As Color)

ColorPickerDesigner

ControlDesigner that makes the SmartTag. Go here for the designer How-to's: UITypeEditorsDemo[^].

ColorPickerSmartTag.jpg

EyeDropper

The EyeDropper button EyeDropperButton.jpg can actually be used as a separate control, if you want. Use the dll or add the Class, and add Dropper.cur Cursor.png as an embedded resource.

Clicking the button activates the control and opens the zoom window. It stays active as long as the mouse button remains pressed. Releasing the mouse button will set the selected color. As the Mouse is moving with the button pressed it is calling the Sub GetScreenShot.

GetScreenShot will determine the rectangular area around the mouse position for the screen shot. Then it calls the CopyFromScreen from the Graphics object to get the Bitmap of that part of the screen. Then using the GetPixel function of the Bitmap on the center point to get the Color of the pixel.

ZoomWindowType - Sets if the zoom window will show in place or show as a Custom Cursor that moves with the mouse. The Custom Cursor uses techniques from the gCursor[^].

ShowSelectedSwatch - Sets if the zoom window will show a swatch of the Selected Color.

ColorPickerSmartTag.jpg

Show Zoom Window In Place

ColorPickerSmartTag.jpg

Show Zoom Window As Custom Cursor

ColorPickerSmartTag.jpg

ZoomLevel

Set the ZoomLevel to change how big the pixels are enlarged in the zoom window.

ColorPickerSmartTag.jpg

Sub GetScreenShot()

    'The Mouse position is in the middle of the zoom box
    '   Determine the upper right corner point 
    '   of the zoom box from the mouse's position
    Dim scrPt As Point = Control.MousePosition
    scrPt.X = CInt(scrPt.X - bmpScreenShot.Width / 2)
    scrPt.Y = CInt(scrPt.Y - bmpScreenShot.Height / 2)

    'Copy the current piece of the screen to the bmpScreenShot Bitmap
    Using g As Graphics = Graphics.FromImage(bmpScreenShot)
        g.CopyFromScreen(scrPt, New Point(0, 0), bmpScreenShot.Size)
    End Using

    'Determine the color of the pixel in the center of the box
    SelectedColor = bmpScreenShot.GetPixel( _
        CInt(bmpScreenShot.Size.Width / 2), _
        CInt(bmpScreenShot.Size.Height / 2))

    Invalidate()

End Sub

gTrackBar RGB Sliders - New in version 1.3

I replaced the Microsoft TrackBars I used for the RGB adjustments with my gTrackBar [^]. Why? It just looks better.

Put the gColorPicker into a DropDown

For an even smaller footprint, you can put the gColorPicker into a dropdown. Here are a couple of options.

ToolStripDropDownButton

Host the gColorPicker in a ToolStripDropDownButton: First declare the gColorPicker and ToolStripDropDownButton.

Private WithEvents gcpToolStripForeColor As ColorPickerLib.gColorPicker = _
    New ColorPickerLib.gColorPicker
Private ReadOnly ToolStripDropDownButton1 As ToolStripDropDownButton = _
    New ToolStripDropDownButton()

Then set it all up in the Form's Load Event.

'Customize the gColorPicker
gcpToolStripForeColor.Value = lblTextSample.ForeColor
gcpToolStripForeColor.BackColor = Color.White
'Create a host for the gColorPicker
Dim Host1 As ToolStripControlHost = _
    New ToolStripControlHost(gcpToolStripForeColor)
Host1.AutoSize = False
'Create a dropdown to put the host in
Dim dropDown1 As New ToolStripDropDown()
dropDown1.Items.Add(Host1)
'Customize the DropDownButton
ToolStripDropDownButton1.Text = "ForeColor"
ToolStripDropDownButton1.DisplayStyle = _
    ToolStripItemDisplayStyle.ImageAndText
ToolStripDropDownButton1.Image = _
    MakeColorSquare(gcpToolStripForeColor.Value)
'Add the DropDownButton to the ToolStrip
ToolStrip1.Items.Add(ToolStripDropDownButton1)
'Add the Dropdown to the button
ToolStripDropDownButton1.DropDown = dropDown1

DropDownContainer

I made a DropDownContainer to put the ColorPicker or any control(s) in the DropDownContainer[^].

Add this code to make the color box in the DropDownContainer:

Private Sub ColorPicker1_ColorPicked(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles ColorPicker1.ColorPicked

    Dim bm As Bitmap = New Bitmap(30, 20)
    Using g As Graphics = Graphics.FromImage(bm)
        g.FillRectangle(Brushes.White, 0, 0, 30, 20)
        g.FillRectangle(New SolidBrush(ColorPicker1.Value), 0, 0, 30, 20)
        DropDownContainer1.GraphicImage = bm.Clone
        bm.Dispose()
    End Using

    DropDownContainer1.CloseDropDown()

End Sub

ColorPickeInDropDown.jpg

Replace the MS Color Editor for the Color Property

If you want to use the gColorPicker instead of the standard one, just reference the ColorPickerLib and add this Attribute to the property:

<Editor(GetType(gColorPickerDDEditor), GetType(UITypeEditor))> _

For example:

<Editor(GetType(gColorPickerDDEditor), GetType(UITypeEditor))> _
Public Property BorderColor() As Color
    Get
        Return _borderColor
    End Get
    Set(ByVal Value As Color)
        _borderColor = Value
        Invalidate()
    End Set
End Property

ColorPickeInPropGrid.jpg

How this works is fully explained in my UITypeEditor article: UITypeEditorsDemo[^].

gColorComboBox and gEnumBox

These are a couple of additional controls added to the library. They are extensions of the ComboBox. The gColorComboBox lists all the known colors along with a color swatch sample. The gEnumBox takes three enumerations commonly used when I have been editing colors and adds a sample example to the dropdown items. Rather than create a whole new project and library, I decided to add them to this one.

DashStyle

EmumHatch.png

HatchStyle

EmumHatch.png

LineJoin

EmumHatch.png

So I did not have to make three separate controls, I added a property that lets you update the ComboBox Items with the items in the chosen enumeration.

Enum eStyle
    DashStyle
    HatchStyle
    LineJoin
End Enum

Private _enumStyle As eStyle = eStyle.Dashstyle

Public Property EnumStyle() As eStyle
    Get
        Return _enumStyle
    End Get
    Set(ByVal Value As eStyle)
        _enumStyle = Value
        Items.Clear()
        If Not DesignMode Then
            Select Case Value
                Case eStyle.DashStyle
                    Items.AddRange([Enum].GetNames(GetType(DashStyle)))
                Case eStyle.HatchStyle
                    Items.AddRange([Enum].GetNames(GetType(HatchStyle)))
                Case eStyle.LineJoin
                    Items.AddRange([Enum].GetNames(GetType(LineJoin)))
            End Select
        End If
    End Set
End Property

Then in the DrawItem event, it draws the Item according to the current EnumStyle.

History

  • Version 1.0 - October 2008
  • Version 1.1 - October 2008
    • Moved RaiseEvent ColorChanging(Me) out of the Sub UpdateColor and into the Value Set Property block and removed the unnecessary code from the Sub UpdateColor to catch holes in the ColorChanging Event.
  • Version 1.2 - December 2008
    • Updated code to comply with Option Strict turned On
    • Fixed small glitch in Initializing the control
    • Updated Mouse Events
  • Version 1.3 - April 2009
    • Added new custom RGB Trackbar Sliders
  • Version 1.4 - September 2011
    • Added CurrentColor and ClosestColorName to ColorPicked event
    • Auto set Sat and Bright to 100 when color is black and Hue is Clicked
    • Removed the hardcoded KnownColor list and use the new SortColors function
  • Version 1.5 - September 2011
    • Added Custom Cursor option to the EyeDropper
  • Version 1.6 - September 2011
    • Added demonstration of how to add gColorPicker to a ToolStrip
  • Version 1.7 - October 2011
    • Moved the initialization of the color list in the gColorComboBox to stop multiple loading of the list
    • Added the new gEnumBox for easier style formatting
    • Added some properties to the gColorComboBox to match the gEnumBox
  • Version 1.8 - January 2012
    • Added UITypeEditor so the gColorPicker can be used in the PropertyGrid

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here