Click here to Skip to main content
15,868,236 members
Articles / Programming Languages / C#
Article

Custom Color Dialog Box

Rate me:
Please Sign up or sign in to vote.
4.45/5 (18 votes)
14 Mar 2006CPOL4 min read 130.9K   3K   29   18
Custom Color Dialog Box
Custom_Color_Dialog_Box.PNG

Introduction

The common dialog boxes on Windows are sufficient for most users. However there are always requirements where these dialog boxes need customization. I wanted users to choose not only color but specify the alpha values from the ColorDialog box. I customized the default ColorDialog box using Win32 API. There are some hacks, some dirty C# code (I am new to C# so any suggestions to improve code is very much welcome), but finally I have a customized C# ColorDialog box control where the user can not only choose the color but also specify the alpha value.

Using the Code

To use this CustomColorDialog, there are some fairly simple steps as listed below:

  • Add the CustomColorDialog.dll in references
  • Setup the namespace use:

    C#
    using CustomCommonDialog; 
  • Create the CustomColorDialog object and call show:

    C#
    CustomColorDialog colDlg = new CustomColorDialog(Handle);
    bool f = colDlg.Show(); 
  • Get the color component values from the dialog box:

    C#
    if( f )
    {
       System.Drawing.Color col = colDlg.SelectedColor;
       int a = col.A;
       int r = col.R;
       int g = col.G;
       int b = col.B;
    }

The Background

To customize a Color dialog box, you can use any of the following methods:

  • Specify values in the CHOOSECOLOR structure when you create the dialog box
  • Provide a custom template
  • Provide a hook procedure

You can modify the appearance and behavior of the Color dialog box by setting flags in the Flags member of the CHOOSECOLOR structure. For example, you can set the CC_SOLIDCOLOR flag to direct the dialog box to display only solid colors. To cause the dialog box to initially select a color other than black, set the CC_RGBINIT flag and specify a color in the rgbResult member.

You can provide a custom template for the Color dialog box, for example, if you want to include additional controls that are unique to your application. The ChooseColor function uses your custom template in place of the default template.

To Provide a Custom Template for the Color Dialog Box

  1. Create the custom template by modifying the default template specified in the Color.dlg file. The control identifiers used in the default Color dialog template are defined in the Color.dlg file.
  2. Use the CHOOSECOLOR structure to enable the template as follows:
    • If your custom template is a resource in an application or dynamic link library, set the CC_ENABLETEMPLATE flag in the Flags member. Use the hInstance and lpTemplateName members of the structure to identify the module and resource name.

    -Or-

    • If your custom template is already in memory, set the CC_ENABLETEMPLATEHANDLE flag. Use the hInstance member to identify the memory object that contains the template.

You can provide a CCHookProc hook procedure for the Color dialog box. The hook procedure can process messages sent to the dialog box. It can also use registered messages to control the behavior of the dialog box. If you use a custom template to define additional controls, you must provide a hook procedure to process input for your controls.

To Enable a Hook Procedure for the Color Dialog Box

  1. Set the CC_ENABLEHOOK flag in the Flags member of the CHOOSECOLOR structure
  2. Specify the address of the hook procedure in the lpfnHook member

After processing its WM_INITDIALOG message, the dialog box procedure sends a WM_INITDIALOG message to the hook procedure. The lParam parameter of this message is a pointer to the CHOOSECOLOR structure used to initialize the dialog box.

The dialog box sends the COLOROKSTRING registered message to the hook procedure when the user clicks the OK button. The hook procedure can reject the selected color and force the dialog box to remain open by returning zero when it receives this message. The hook procedure can force the dialog box to select a particular color by sending the SETRGBSTRING registered message to the dialog box. To use these registered messages, you must pass the COLOROKSTRING and SETRGBSTRING constants to the RegisterWindowMessage function to get a message identifier. You can then use the identifier to detect and process messages sent from the dialog box, or to send messages to the dialog box.

The Classes

There are following three classes in the CustomCommonDialog namespace that must be mentioned:

  • CustomColorDialog - The main class that wraps up all the code for launching and modifying default choose color dialog box
  • NativeMethods - This class wraps all the WinAPI function calls and data types
  • AlphaSlider - Custom user control to show the slider control for alpha values

Inside the Main CustomColorDialog Class

The following variables are used in the class:

C#
// the CHOOSECOLOR structure, used to control the appearance and behaviour
// of the OpenFileDialog
private ChooseColor _cc;

// the slider control to change the alpha values
private AlphaSlider _sliderAlpha;

// the textbox to show current alpha value
private TextBox _textAlpha;

// the panel to contain the slider and text box
private Panel _panelAlpha;

// final color value
private System.Drawing.Color _color;

The constructor initializes the ChooseColor structure:

C#
// create the ChooseColor structure to pass to WinAPI

_cc.lStructSize = Marshal.SizeOf( _cc );
_cc.lpfnHook = new CCHookProc(MyHookProc); //hook function

//enable hook
_cc.Flags = ChooseColorFlags.FullOpen | ChooseColorFlags.EnableHook;
_cc.hwndOwner = handle; //set the owner window

Int32 temp = 0;
IntPtr CustColor = Marshal.AllocCoTaskMem( 16 * Marshal.SizeOf(temp));

//fill in the value to load custom colors with these values
_cc.lpCustColors = CustColor; //set the custom color buffer

The main window hook for the dialog box places the custom controls on the dialog box in WM_INITDIALOG message:

C#
//increase the width of the default dialog box
//place the slider and text box controls on the right

POINT topLeft = new POINT();
POINT bottomRight = new POINT();

IntPtr ipNotify = new IntPtr( lParam );

ChooseColor cc = (ChooseColor)Marshal.PtrToStructure( ipNotify,
    typeof(ChooseColor) );

IntPtr hWndParent = NativeMethods.GetParent( hWnd );
NativeMethods.SetParent( _panelAlpha.Handle, hWnd);

RECT rc = new RECT();
NativeMethods.GetWindowRect( hWnd, ref rc );

topLeft.X = rc.right;
topLeft.Y = rc.top;
NativeMethods.ScreenToClient( hWnd, ref topLeft );

bottomRight.X = rc.right;
bottomRight.Y = rc.bottom;
NativeMethods.ScreenToClient( hWnd, ref bottomRight );

Rectangle rcClient = _panelAlpha.ClientRectangle;
NativeMethods.MoveWindow( hWnd, rc.left, rc.top,
         bottomRight.X+rcClient.Width+10, bottomRight.Y+28, true );

The Final OnOk

This is a total hack. I could not find the message posted by ChooColor dialog when user presses OK. I found the last message sent and use it.
TO DO: Find the correct message as documented i.e. COLOROKSTRING.

C#
if( msg == 0xC072 /*==COLOROKSTRING*/)
{
  //get the current ChooseColor structure
  IntPtr ipNotify = new IntPtr( lParam );
  ChooseColor cc = (ChooseColor)Marshal.PtrToStructure( ipNotify,
      typeof(ChooseColor) );

  IntPtr hWndParent = NativeMethods.GetParent( hWnd );

  //extract the RGB values from structure
  int R = (char )(cc.rgbResult);
  int G = (char )(((int)(cc.rgbResult)) >> 8);
  int B = (char )(cc.rgbResult >> 16);

  //the typecase problem
  //TODO: write the C# version of GetRValue, GetGValue, GetBValue
  if( R > 256 )
     R = R/257;
  if( G > 256 )
    G /= 257;

  //get the alpha value from slider control
  _color = Color.FromArgb(_sliderAlpha.Value,R, G, B);

  Trace.WriteLine(_color);
}

To Do

Add the following CustomDialogBoxes in the CustomCommonDialog namespace:

  • Font Dialog Box
  • Open and Save As Dialog Box
  • Print Dialog Box

I hope this article would help many to customize the color dialog boxes according to their need. Writing this article gave me a chance to learn C#.

History

  • 15th March, 2006: Initial post

License

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


Written By
Web Developer
Hong Kong Hong Kong
innovating, managing and developing next generation media products and services

Comments and Discussions

 
Questionerror i am getting: Pin
Member 1353418818-Dec-21 16:04
Member 1353418818-Dec-21 16:04 
SuggestionsliderAlpha is changed when textAlpha changed Pin
rpgmajor15-Dec-11 21:49
rpgmajor15-Dec-11 21:49 
GeneralMy vote of 4 Pin
Rajeev Dhiman30-Nov-11 20:08
Rajeev Dhiman30-Nov-11 20:08 
NewsSome bugs fixed. Pin
koci_m26-Oct-11 2:30
koci_m26-Oct-11 2:30 
GeneralMy vote of 1 Pin
Member 80321387-Jul-11 1:49
Member 80321387-Jul-11 1:49 
GeneralRe: My vote of 1 Pin
Gophern Kwok2-Dec-12 14:54
Gophern Kwok2-Dec-12 14:54 
GeneralCannot save custom colors Pin
StevenHSLee12-Oct-10 17:02
StevenHSLee12-Oct-10 17:02 
GeneralCustomize Pin
rejectkosta15-Jan-10 4:02
rejectkosta15-Jan-10 4:02 
GeneralMy vote of 1 Pin
Steve Duke2-Dec-09 5:48
Steve Duke2-Dec-09 5:48 
GeneralInitial Color : BUG Pin
baranils21-Jul-09 6:04
baranils21-Jul-09 6:04 
QuestionCustomColors? Pin
Tim8w19-Jun-08 7:15
Tim8w19-Jun-08 7:15 
GeneralInitial color Pin
erik88827-May-08 21:47
erik88827-May-08 21:47 
GeneralI get 0 value always Pin
kiquenet.com29-Apr-08 8:47
professionalkiquenet.com29-Apr-08 8:47 
Generalbuild a user control instead Pin
Gong Liu17-Aug-07 7:37
Gong Liu17-Aug-07 7:37 
can't you just build a user control that consists of a regular ColorDialog control and a slider control for selecting Alpha value? It sounds easier to me.

GL
GeneralRe: build a user control instead Pin
HowitZer2610-May-13 8:17
HowitZer2610-May-13 8:17 
GeneralBad color casting Pin
crono531-Jul-07 20:38
crono531-Jul-07 20:38 
GeneralCustomize ColorDialog Pin
nizwiz.198520-May-07 17:54
nizwiz.198520-May-07 17:54 
GeneralCOLOROKSTRING problem solved Pin
Matteo Prosperi14-May-07 2:59
Matteo Prosperi14-May-07 2:59 

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.