Design-time mouse interactions.
The property grid used at design time is
a great tool but sometime it'd be great just to grab a little handle on a
control to tweak a property that was wholly visual in nature. For example, a
control that draws an elliptically shaded background could have it's focus point
dragged around at design-time.
Visual Studio.NET doesn't directly
enable this sort of interaction but with a little tweak or two it's possible to
create a designer that does.
Hit testing
Whenever the mouse moves in a control at
design time the ControlDesigner.GetHitTest method is called to determine whether
the designer needs to process mouse clicks itself or pass them on to the
control. It's possible to check for the presence of the mouse in a specific
area, such as a grab-handle, and return true or false from this method.
Getting the message
Controls running in the designer are
"live" so they can still do all the things they can do at runtime. In the case
of a simple designer that uses the mouse to manipulate a property it's possible
to use the controls own events to drive the design process. The designer can add
handlers to the events of the control and act upon those events as needed. When
the designer is disposed the events can be unhooked and the control left
unencumbered. In the demonstration that goes with this article, the Initialize
and Dispose methods of the ControlDesigner are overridden to add handlers to the
MouseUp, MouseDown and MouseMove events of the control.
User feedback
When the mouse is moved in the designer,
the ControlDesigner.SetCursor method is called to allow an opportunity to change
the mouse cursor. This enables us to change to a pointer or the hand icon
whenever the mouse is in an interesting area.
The designer also has an opportunity to
paint extra graphics on the design surface in response to the OnPaintAdornments
method call. This enables the designer to display the grab-handles or other
visual clues to what's going on.
Changing the properties
The actual changing of data in the
control should be done via the PropertyInfo object for the specific property
wherever possible. This enables the property grid in the designer to keep up
with changes that you make. You can obtain a MemberInfo object from the
reflected members of the control using the TypeDescriptor class. You can then
get and set the values in the Control based object and call
ControlDesigner.RaiseComponentChanging followed by
ComponentDessigner.RaiseComponentChanged.
Demonstrating the idea.
The FilledGroupBox control draws a
simple group box with a background filled with a complex gradient. Figure1 shows
the control in action.

Figure 1. The FilledGroupBox control.
The focus point for the "shine" on the
box is adjusted at design time using a simple rectangular grab-handle as shown
in Figure 2.

Figure 2. The FilledGroupBoxDesigner in
action.
The code for the FilledGroupBox and it's
related designer can be seen in this listing.
You can find the Source Code files here.
Return to the main index