65.9K
CodeProject is changing. Read more.
Home

WYSIWYG Color and Font CommonDialogs

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.74/5 (8 votes)

Jun 7, 2006

CPOL

2 min read

viewsIcon

46556

downloadIcon

338

Enhancing user pleasure, or how to get the current user choice from a running dialog.

Introduction

The Color and Font Common Dialogs use a small sample window to show the current user choice. If your application draws fast enough, why not display the resulting color/font directly in the application? This way, the specified part can be seen in relation to the overall appearance. This submission uses derived ColorDialog/FontDialog classes, that signal the current user choice while the dialog is still running. To evaluate this improved WYSIWYG functionality, try the provided demo.

FontDialog

To catch a change in the user's choice, the sample window is monitored by a NativeWindow class, which is created on the WM_INITDIALOG message in the overridden HookProc method. Whenever the WM_GETTEXT message is received, a click on the hidden Apply button is simulated. As the .NET FontDialog exposes an Apply event with a virtual OnApply method, the Font and Color properties now hold the actual choice. To filter out unwanted events, the new values are compared to the last signaled values. On a real change, the FontChanged event is raised, indicating whether the font and/or font color have changed. Surprisingly, this works only with a hidden Apply button (ShowApply == false), but this would be useless anyway with our improved WYSIWYG functionality.

ColorDialog

Here, the WM_PAINT message is trapped, but the dialog is then notified by means of an interface defined method. There is no built-in way to get the actual color value, so we ask the RGB editboxes using GetDlgItemInt. After filtering out the ordinary repainting of the sample window, we fire the ColorChanged event with the new value. The dialog must be run in FullOpen mode, otherwise the sample window is not created.

Since we already use a derived dialog, the CustomColors property is shadowed to provide the Color type instead of the int array that the base class exposes. Furthermore, a boolean ShouldSerializeCustomColors property indicates whether the user changed any custom color(s).

Using the code

Setting the form's BackColor using an anonymous method is done as shown below:

ocColorDialog dlg = new ocColorDialog();
dlg.Color = this.BackColor;

dlg.ColorChanged = delegate(object sender, ColorChangedEventArgs e)
    { this.BackColor = e.CurrentColor; };
    
if (dlg.ShowDialog() == DialogResult.Cancel)
{
    this.BackColor = dlg.Color;
}

Setting the UseCancelEvent property simplifies the coding for the case of the dialog cancellation:

dlg.UseCancelEvent = true;
dlg.ShowDialog();

Points of Interest

Will I ever see this technique applied in a (commercial) application?