Introduction
For a project I'm working on I needed something more stylish than the
standard color dialog, which comes with .NET, so I decided to make a color
picker dialog of my own. I used the one found at Microsoft Office (for choosing
the font color) as a source of inspiration (in fact, I shamelessly copied it) -
I used exactly the same palette of 40 colors and the same "look and feel" - only
the size and distance of the little color panels is a little different in my
version.
Using the code
The code for the color dialog is very straightforward and offers
nothing unusual. It has only about 200 lines of code and should be
self-explaining. The control is a form with 40 small panel controls, which have
event handlers for mouse messages attached to them. The constructor receives the
coordinates of the point it is supposed to appear at as arguments (usually the
calling button of the container form). When closed, the color dialog returns the
chosen color. The dialog can be alternatively closed by hitting Escape or Enter
(by using an "invisible" Escape button). In my small demo program the background
color changes according to the chosen color. A standard color dialog is called
from the "More colors..." button.
Public Class
ColorPaletteDialog
Inherits
Form
Private max
As Byte = 40
Private panel(40)
As Panel
Private color(40)
As Color = {Color.FromArgb(0, 0, 0),
Color.FromArgb(153, 51, 0), Color.FromArgb(51, 51, 0),_
Color.FromArgb(0, 51, 0), Color.FromArgb(0, 51, 102), Color.FromArgb(0, 0, 128),
Color.FromArgb(51, 51, 153),_
Color.FromArgb(51, 51, 51), Color.FromArgb(128, 0, 0), Color.FromArgb(255, 102,
0), Color.FromArgb(128, 128, 0),_
Color.FromArgb(0, 128, 0), Color.FromArgb(0, 128, 128), Color.FromArgb(0, 0,
255), Color.FromArgb(102, 102, 153),_
Color.FromArgb(128, 128, 128), Color.FromArgb(255, 0, 0), Color.FromArgb(255,
153, 0), Color.FromArgb(153, 204, 0),_
Color.FromArgb(51, 153, 102), Color.FromArgb(51, 204, 204), Color.FromArgb(51,
102, 255), Color.FromArgb(128, 0, 128),_
Color.FromArgb(153, 153, 153), Color.FromArgb(255, 0, 255), Color.FromArgb(255,
204, 0), Color.FromArgb(255, 255, 0),_
Color.FromArgb(0, 255, 0), Color.FromArgb(0, 255, 255), Color.FromArgb(0, 204,
255), Color.FromArgb(153, 51, 102),_
Color.FromArgb(192, 192, 192), Color.FromArgb(255, 153, 204),
Color.FromArgb(255, 204, 153), Color.FromArgb(255, 255, 153),_
Color.FromArgb(204, 255, 204), Color.FromArgb(204, 255, 255),
Color.FromArgb(153, 204, 255), Color.FromArgb(204, 153, 255), _
Color.FromArgb(255, 255, 255)}
Private
colorName(40) As
String = {"Black", "Brown", "Olive Green",
"Dark Green", "Dark Teal", "Dark Blue", "Indigo",_
"Gray-80%", "Dark Red", "Orange", "Dark Yellow", "Green", "Teal", "Blue",
"Blue-Gray", "Gray-50%", "Red", "Light Orange",
"Lime", "Sea Green", "Aqua", "Light Blue", Violet}
End
Class 'ColorPaletteDialog
Dim
moreColorsButton As
New Button()
Dim
cancelButton As
New Button()
Dim
selectedColor As Color
Public
Sub New(x
As Integer,
y As
Integer)
Size = New
Size(158, 132)
FormBorderStyle = FormBorderStyle.FixedDialog
MinimizeBox =(MaximizeBox <<=(ControlBox <<=
False))
ShowInTaskbar = False
CenterToScreen()
Location = New
Point(x, y)
BuildPalette()
moreColorsButton.Text = "More colors ..."
moreColorsButton.Size =
New Size(142, 22)
moreColorsButton.Location =
New
Point(5, 99)
AddHandler moreColorsButton.Click,
AddressOf moreColorsButton_Click
moreColorsButton.FlatStyle = FlatStyle.Popup
Controls.Add(moreColorsButton)
'"invisible" button to
cancel at Escape
cancelButton.Size =
New
Size(5, 5)
cancelButton.Location =
New Point(- 10, - 10)
AddHandler cancelButton.Click,
AddressOf cancelButton_Click
Controls.Add(cancelButton)
cancelButton.TabIndex = 0
Me.CancelButton = cancelButton
End
Sub
'New
Public
ReadOnly
Property Color() As Color
Get
Return selectedColor
End
Get
End Property
Sub
BuildPalette()
Dim pwidth
As Byte = 16
Dim pheight
As Byte = 16
Dim pdistance
As Byte
= 2
Dim border
As Byte = 5
Dim x As
Integer = border
Dim y As
Integer = border
Dim toolTip
As New ToolTip()
Dim i As
Integer
For i = 0 To max - 1
panel(i) = New
Panel()
panel(i).Height = pwidth
panel(i).Width = pheight
panel(i).Location = New
Point(x, y)
toolTip.SetToolTip(panel(i), colorName(i))
Me.Controls.Add(panel(i))
If x < 7 *(pwidth + pdistance)
Then
x += pwidth + pdistance
Else
x = border
y += pheight + pdistance
End If
panel(i).BackColor = color(i)
AddHandler panel(i).MouseEnter,
AddressOf OnMouseEnterPanel
AddHandler panel(i).MouseLeave,
AddressOf OnMouseLeavePanel
AddHandler panel(i).MouseDown,
AddressOf OnMouseDownPanel
AddHandler panel(i).MouseUp,
AddressOf OnMouseUpPanel
AddHandler panel(i).Paint,
AddressOf OnPanelPaint
Next i
End
Sub
'BuildPalette
Sub
moreColorsButton_Click(sender As
Object, e
As System.EventArgs)
Dim colDialog
As New
ColorDialog()
colDialog.FullOpen = True
colDialog.ShowDialog()
selectedColor = colDialog.Color
colDialog.Dispose()
Close()
End
Sub
'moreColorsButton_Click
Sub
cancelButton_Click(sender As
Object, e
As System.EventArgs)
Close()
End
Sub
'cancelButton_Click
Sub
OnMouseEnterPanel(sender As
Object, e
As EventArgs)
DrawPanel(sender, 1)
End
Sub
'OnMouseEnterPanel
Sub
OnMouseLeavePanel(sender As
Object, e
As EventArgs)
DrawPanel(sender, 0)
End
Sub
'OnMouseLeavePanel
Sub
OnMouseDownPanel(sender As
Object, e
As MouseEventArgs)
DrawPanel(sender, 2)
End
Sub
'OnMouseDownPanel
Sub
OnMouseUpPanel(sender As
Object, e
As MouseEventArgs)
Dim panel
As Panel = CType(sender, Panel)
selectedColor = panel.BackColor
Close()
End
Sub
'OnMouseUpPanel
Sub
DrawPanel(sender As
Object, state
As Byte)
Dim panel
As Panel = CType(sender, Panel)
Dim g As
Graphics = panel.CreateGraphics()
Dim pen1, pen2
As Pen
If state = 1
Then 'mouse
over
pen1 = New
Pen(SystemColors.ControlLightLight)
pen2 = New
Pen(SystemColors.ControlDarkDark)
Else
If state = 2
Then
'clicked
pen1 = New
Pen(SystemColors.ControlDarkDark)
pen2 = New
Pen(SystemColors.ControlLightLight)
'neutral
Else
pen1 =
New
Pen(SystemColors.ControlDark)
pen2 = New
Pen(SystemColors.ControlDark)
End If
End If
Dim r As Rectangle =
panel.ClientRectangle
Dim p1 As
New Point(r.Left, r.Top)
'top left
Dim p2
As New
Point(r.Right - 1, r.Top) 'top right
Dim p3
As New
Point(r.Left, r.Bottom - 1) 'bottom left
Dim p4
As New
Point(r.Right - 1, r.Bottom - 1) 'bottom right
g.DrawLine(pen1, p1, p2)
g.DrawLine(pen1, p1, p3)
g.DrawLine(pen2, p2, p4)
g.DrawLine(pen2, p3, p4)
End
Sub
'DrawPanel
Sub
OnPanelPaint(sender As [Object], e
As PaintEventArgs)
DrawPanel(sender, 0)
End
Sub
'OnPanelPaint.
Points of Interest
The little panels show the name of the selected color under the curser
inside a tool tip. They also change their appearance, when the mouse hovers over
them or clicks them. In order to do this, the Paint method for the panel is
overloaded and we draw the borders of the panel ourselves (using System colors),
dependant of the state of the mouse.