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?
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.