The ColorPicker Controls have been updated to version

This is a fairly substantial update, with quite a few bug fixes and enhancements to the code.

What's next for the library?

I feel the code is starting to get a little bloated as the library is trying to serve two purposes - the primary purpose is for the selection of colours. However, it also provides the ability to load and save colour swatches in various formats, some of which has been the subject of posts on this blog.

Internally, we link to the individual files from the library in our core product assemblies - all the UI stuff is in Cyotek.Windows.Forms, and everything else is in Cyotek.Drawing. I think it would probably be a good idea to properly split up this library too. If you just want the UI, use one library, if you want the extended palette serialisation support, use the other. There is some overlap though so this will need to be considered a bit first.

Of course splitting the library is a massive breaking change. I think future versions of our open source libraries will change to use Semantic Versioning so that it will be much clearer when things are being broken. Of course, it would be preferable if breaking changes weren't introduced all the time! This is also why I haven't added a NuGet package yet, when you update a package you don't expect to have to change your source code too.

Changes and new features

  • Added new AdobePhotoShopColorSwatchSerializer serializer for reading and writing Adobe PhotoShop colour swatches (both version 1 and version 2)
  • You can now set the Columns property of a ColorGrid control to 0, which will then internally calculate columns based on the size of the control, the cell size, and the spacing. A new read-only ActualColumns property has been added which will allow you to get the real number of columns if required. The AutoSize behaviour has been changed so that only the vertical height of the control is adjusted when Columns is zero
  • Save Palette button in the ColorPickerDialog now obtains the serializer to use based on the selected filter index, allowing correct saving if multiple serializers use the same extension.
  • Added CanReadFrom method to IPaletteSerializer.
  • PaletteSerializer.GetSerializer now makes use of the above new method to access the relevant serializer rather than just matching extensions. This means if you have two serializers that support different .pal formatted files, these can now be loaded successfully, instead of one loading and one failing.
  • Added new RawPaletteSerializer which reads and writes palettes that are simply RGB triplets in byte form
  • Added new ShowAlphaChannel property to ColorEditor and ColorPickerDialog. This property allows the alpha channel editing controls to be hidden, for when working with 8-bit colours.
  • The rendering of the selected cell in a ColorGrid control who's SelectedCellStyle is Zoomed now uses Padding.Left and Padding.Top to determine the size of the zoom box, avoiding massive boxes the larger the CellSize gets.
  • Added a new standard 256 colour palette. You can use this in the ColorGrid by setting the Palette property to ColorPalette.Standard256 or obtain the array of colours by calling ColorPalettes.StandardPalette
  • ColorGrid and RgbaColorSlider controls now only create transparency brushes when required. A new virtual method SupportsTransparentBackColor allows inheritors to create their own brushes if required.
  • Added EditingColor event to ColorGrid, allowing the edit colour action to be cancelled, or replaced with a custom editor
  • Added CurrentCell property and GetCellOffset methods to the ColorGrid.
  • ColorCollection now implements IEquatable
  • Added more tests
  • Added new Navigate method to ColorGrid for easier moving within the cells of the grid

Bug Fixes

  • The ColorGrid control now tries to be smarter with painting, and only paints cells that intersect with the clip rectangle. In addition, where possible only individual cells are invalidated rather than the entire control.
  • Corrected invalid error messages from the Save Palette button in the ColorPickerDialog.
  • Load Palette and Save Palette buttons in the ColorPickerDialog now check the CanRead and CanWrite properties of the serializer.
  • Double clicking with any button other than the left in ColorGrid control no longer attempts to initiate colour editing
  • Setting the Color property of the ColorGrid control to Color.Empty no longer treats the value as a valid colour
  • The ColorGrid control no longer defines custom colour regions when the ShowCustomColors property was false. This manifested in hover and selection effects working if you moved your mouse over the bottom of a resized grid.
  • Clicking "white space" areas of a ColorWheel control will no longer incorrectly set the colour to the closest matching point on the wheel itself. However, starting to select a colour within the wheel and then moving outside the bounds will continue to select the closest match as usual.
  • Fixed a crash that occurred when creating controls that inherited from ColorGrid or RgbaColorSlider
  • When the AutoAddColors and ShowCustomColors properties are false, unmatched colours will no longer be silently added to the ColorGrid custom palette unexpectedly. This also resolves various crashes after the colour regions fix above was applied.
  • The ColorWheel control now makes use of ButtonRenderer.DrawParentBackground to draw itself, to avoid ugly blocks of solid colours when hosted in containers such as the TabControl
  • The ColorEditorManager control's ColorChanged event has now been marked as the default event, so when you double click the component in the designer, a code window now correctly opens.
  • If the underlying entry in a ColorCollection bound to a ColorGrid control was modified, and this particular entry was the selected colour, the ColorGrid would not keep its Color property in sync and would clear the selected index.
  • Attempting to set the Columns property to less than zero now throws an ArgumentOutOfRange exception rather than setting it, then crashing later on
  • Double clicking a colour in the grid of the ColorPickerDialog no longer opens another copy of the ColorPickerDialog
  • Fixed problems in the ColorGrid with keyboard navigation and initial focus if no valid colour index was set.
  • The ColorCollection.Find method now correctly works when adding named colours (e.g. Color.CornflowerBlue) to the collection, but searching by ARGB value (e.g. Color.FromArgb(100, 149, 237))
  • Fixed an issue where if the internal dictionary lookup in ColorCollection class had been created and the collection was then updated, in some cases the lookup wasn't correctly modified.

Update History

  • 2014-04-13 - First published
  • 2020-11-21 - Updated formatting

Like what you're reading? Perhaps you like to buy us a coffee?

Donate via Buy Me a Coffee

Donate via PayPal


# wmjordan

Very nice work! Is it possible to develop a ToolStripItem which pops up a ColorPicker control when clicked? Would you develop this, everybody can benifit from it.


# Richard Moss


Thanks for your comment, glad you like it. While I don't think such a control would be a core part of the library, it ought not to be too complicated to create, I'll have a look at that when I have some free time.

Regards; Richard Moss


# Squas


The control is lovely, no problems so far! :)

Just one request/question:

Is/would it be possible to get an event in ColorPickerDialog informing that the color is being changed inside the dialog (but the dialog not being dismissed).

I'd like to use ColorPickerDialog to pick a color in a object in a game I'm doing, but having to dismiss the dialog every time makes the process very little "WYSIWYG"ish. It'd be great if every time the Dialog changes the currently selected color, an event would be generated, so I could update the object color in realtime and not dismissing the ColorPickerDialog until the color is the one I like

Thanks a lot!


# Richard Moss


I don't think I built one in as I assumed that anyone who wanted more advanced functionality would drop the controls onto a form of their own and then use the ColorEditorManager to bind them together and get a change event. However, it would be fairly straightforward to add - I'll take a look at that.

Regards' Richard Moss


# Richard Moss

The latest version now supports this.