Click here to Skip to main content
15,878,852 members
Articles / Desktop Programming / WPF

WPF Color Picker Like Office 2007

Rate me:
Please Sign up or sign in to vote.
4.89/5 (61 votes)
17 Jan 2010CPOL3 min read 127.7K   7.4K   57   35
A simple to use Color Picker with advanced color palette for WPF Applications with look and feel of Office 2007 color picker
main.JPG >

Introduction

Recently, I was working on a WPF application which required a color picker for setting colors of various graph elements within the application. At first, this seemed like a five minute task for me as I was quite confident that I would get one for free on the internet. I was quite right until I was told that it should have a look and feel like that of Office 2007 color picker. Thus I built my own and here it is.

Features

The Color picker has the following features:

  • Choose color from a predefined list of colors
  • Choose custom color from a Color palette
  • Adjust the opacity of the selected color using a slider in custom color selection mode
  • Ease of use anywhere within a WPF application with a single bindable property for the selected color.

Implementation

The source code supplied is very much self explanatory and easy to understand. So I will highlight the points of interest. Let's begin with the how to use it in our application.

Basically the control has three files, so I have packaged it in a DLL.

XML
<CustomWPFColorPicker:ColorPickerControlView x:Name="ForeColorPicker" />

The Control has a dependency property "CurrentColor" which gets updated when a color is picked from the picker either from the predefined list of colors or the advanced color palette.

C#
public static DependencyProperty CurrentColorProperty = 
DependencyProperty.Register("CurrentColor", typeof(SolidColorBrush),
typeof(ColorPickerControlView), new PropertyMetadata(Brushes.Black)); 

The picker is a ToggleButton with little style edited to show the CurrentColor inside <border>. A Popup holds the predefined colors as in Office 2007. These are a set of buttons each representing a color via the command parameter.

XML
<Button Click="Button_Click"  Style="{StaticResource ColorButtonStyleFirstRow}"
Command="{x:Static CustomWPFColorPicker:ColorPickerControlView.SelectColorCommand}" 
CommandParameter="#FFFFFF" Margin="3,4,3,4" Background="#FFFFFF" />

1.JPG

The "More Colors" button is used to open a model dialog containing the Advanced Picker where a user can select a color from a color palette with the mouse.

2.JPG

The color palette is a JPG image from which 4 bits are read during mousedown event, containing the colors for ARGB.

C#
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                var cb = new CroppedBitmap((BitmapSource)
		(((Image)e.Source).Source), new Int32Rect
		((int)Mouse.GetPosition(e.Source as Image).X, 
		(int)Mouse.GetPosition(e.Source as Image).Y, 1, 1));
                _pixels = new byte[4];
                try
                {
                    cb.CopyPixels(_pixels, 4, 0);
                    UpdateCurrentColor();
                    UpdateMarkerPosition();
                }
                catch
                {
                }
                UpdateSlider();
            }
            catch (Exception)
            {
            }
        }

Using these bits, the color is updated:

C#
private void UpdateCurrentColor()
        {
            CurrentColor = Color.FromRgb(_pixels[2], _pixels[1], _pixels[0]);
            currentColorBorder.Background = 
	     new SolidColorBrush(Color.FromRgb(_pixels[2], _pixels[1], _pixels[0]));
            brightnessSlider.Value = 0.5;
            SelectedCurrentColor = new SolidColorBrush(CurrentColor);
        }

3.JPG

A slider is used to adjust the color value in order to let the user get more shades of the color selected from white to black. I have edited the style of the default WPF slider control to get the look that you see in the demo. Its background reflects the color shades that the users will get when they change the value. For achieving this, I have used a LinearGradientBrush which has 3 GradientStop at point 0, 0.5 and 1. At zero the color is white, at 0.5 the color is the selected color and at 1 it is black.

XML
<LinearGradientBrush x:Key="BrightnessGradient" StartPoint="0,1" EndPoint="0,0" 
        ColorInterpolationMode="ScRgbLinearInterpolation">
            <GradientStop Offset="0" Color="sc# 1, 0,0,0" />
            <GradientStop Offset="0.5" Color="sc# 1, 0.5,0.5,0.5" />
            <GradientStop Offset="1" Color="sc# 1, 1,1,1" />
        </LinearGradientBrush>

As the slider value is changed, I calculate the color value based on the value of the slider. There are two special cases to consider here. When the slider value is nearing 0, the color should near more to White. When the slider value is nearing 1, it should near to Black. At 0 the color becomes white and at 1 it's Black. For this, I have devised an efficient algorithm which is very simple to understand. Note that here I am not simply changing the alpha value of the color, but calculating shades of the color from white to black with the selected color and the color whose shade is being adjusted.

C#
void BrightnessSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (_pixels == null)
            {
                _pixels = new byte[3];
                _pixels[2] = CurrentColor.R;
                _pixels[1] = CurrentColor.G;
                _pixels[0] = CurrentColor.B;
            }

            var nc = Color.FromRgb(_pixels[2], _pixels[1], _pixels[0]);
            var f = (float)e.NewValue;
            float r, g, b;
            const float a = 1;

            if (f >= 0.5f)
            {
                r = nc.ScR + (1 - nc.ScR) * (f - 0.5f) * 2;
                g = nc.ScG + (1 - nc.ScG) * (f - 0.5f) * 2;
                b = nc.ScB + (1 - nc.ScB) * (f - 0.5f) * 2;
            }
            else
            {
                r = nc.ScR * f * 2;
                g = nc.ScG * f * 2;
                b = nc.ScB * f * 2;
            }

            CurrentColor = Color.FromScRgb(a, r, g, b);
            currentColorBorder.Background = new SolidColorBrush(CurrentColor);
        }

Conclusion

The most impressive part of the control is the slider which calculates shades of the selected color. I hope the control is useful to many out there who require an Office 2007 style color picker. Please vote for the article if you find it interesting.

History

  • 17th January, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United Kingdom United Kingdom
Currently living and working in London. He is an enthusiastic software developer passionate about microsoft technologies, specially C#, WPF, Silverlight WCF and windows Azure. Contributes to several open source project and msdn forums.

My Blog
twitter : @sarafuddin

Comments and Discussions

 
QuestionWpf Custom ColorPicker - How to set the TranslateTransform for the selected color in custom color picker control Pin
Member 1186054025-Aug-20 22:07
Member 1186054025-Aug-20 22:07 
Questionvery good Pin
BillW3310-Aug-11 4:35
professionalBillW3310-Aug-11 4:35 
AnswerRe: very good Pin
Saraf Talukder10-Aug-11 4:41
Saraf Talukder10-Aug-11 4:41 
QuestionBrightnessSlider? Pin
Yet another user12-Feb-11 22:34
Yet another user12-Feb-11 22:34 
NewsCustomized size [modified] Pin
Yet another user12-Feb-11 20:36
Yet another user12-Feb-11 20:36 
GeneralMy vote of 5 Pin
Saraf Talukder16-Jan-11 3:06
Saraf Talukder16-Jan-11 3:06 
QuestionWorks with Windows Forms? Pin
stapia.gutierrez6-Jan-11 2:28
stapia.gutierrez6-Jan-11 2:28 
AnswerRe: Works with Windows Forms? Pin
Saraf Talukder7-Jan-11 10:59
Saraf Talukder7-Jan-11 10:59 
GeneralMy vote of 4 Pin
Slacker00730-Dec-10 4:22
professionalSlacker00730-Dec-10 4:22 
GeneralRe: My vote of 4 Pin
Saraf Talukder16-Jan-11 3:03
Saraf Talukder16-Jan-11 3:03 
GeneralMy vote of 5 Pin
krisstoddart13-Oct-10 0:09
krisstoddart13-Oct-10 0:09 
GeneralRe: My vote of 5 Pin
Saraf Talukder16-Jan-11 3:04
Saraf Talukder16-Jan-11 3:04 
GeneralMy vote of 5 Pin
LouiseandGraham5-Oct-10 4:12
LouiseandGraham5-Oct-10 4:12 
GeneralRe: My vote of 5 Pin
Saraf Talukder16-Jan-11 3:04
Saraf Talukder16-Jan-11 3:04 
GeneralAdded an event for oncolorselected Pin
Anthony Main27-Jul-10 23:22
Anthony Main27-Jul-10 23:22 
GeneralRe: Added an event for oncolorselected Pin
Saraf Talukder16-Jan-11 3:04
Saraf Talukder16-Jan-11 3:04 
QuestionRe: Added an event for oncolorselected Pin
Fishbox11-Mar-11 5:57
Fishbox11-Mar-11 5:57 
Generalbinding to your control Pin
reyntjesr31-Mar-10 21:00
reyntjesr31-Mar-10 21:00 
GeneralRe: binding to your control Pin
Jonathan Schmidt10-Oct-10 12:01
Jonathan Schmidt10-Oct-10 12:01 
GeneralRe: binding to your control Pin
savamura27-Oct-10 21:39
savamura27-Oct-10 21:39 
GeneralHelp Pin
akshaysoft8-Feb-10 22:26
akshaysoft8-Feb-10 22:26 
GeneralRe: Help Pin
Saraf Talukder16-Jan-11 3:05
Saraf Talukder16-Jan-11 3:05 
GeneralNice Pin
FantasticFiasco21-Jan-10 2:42
FantasticFiasco21-Jan-10 2:42 
GeneralRe: Nice Pin
Saraf Talukder21-Jan-10 6:05
Saraf Talukder21-Jan-10 6:05 
GeneralRe: Nice Pin
FantasticFiasco21-Jan-10 6:19
FantasticFiasco21-Jan-10 6:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.