Introduction
This article shows a custom control based on the standard splitter. The
extension adds click behavior and position and orientation based cursors. The
click behavior implements the standard Minimize/Maximize/Restore behavior.
I hurt my wrist dragging the standard thing around so...there we went. This
article does not tell you how to write custom controls, there are other
articles around doing just that, this one just shows the results of such a
process (have a look at the source, Luke!).
Background
Reducing the amount of required user interaction to achieve goals is always a
good thing. The standard splitter bar requires dragging to set its position to
one of its extremes. When dragged the previous position is lost. Dragging to
extremes can be replaced by clicking to extremes and in the process it can keep
the last position for a restore click later on. A peace of funny cake and a
nice way to fool around while looking for a way to use embedded resources which
led to the position and orientation based cursors that indicate what a simple
click can lead to.
Using the code and the control
The ClickableSplitter
can be added to the toolbox like any other
custom control. It has a new custom attribute named UseCursors
in
category Behavior
. Its default value is false
so in
order to see the new cursors in action you have to set this property to true
.
The cursor shown and the result of clicking (which are directly related, i.e.
the cursor shows what the effect of clicking will be) follow a counter clock
wise pattern.
And then, on to some code pin pointing some critical snips:
The constructor uses the
GetManifestResourceStream
member of the
Assembly
class to load the embedded cursors. This process can be
improved upon by using static data and a property to load the cursors, but, as
indicated in the extensively commented code, that is left as an exercise for
the reader, although I might post an update showing that at a later time when
time permits.
public ClickableSplitter()
{
Assembly assembly = GetType().Assembly;
AssemblyName assemblyName = assembly.GetName();
for(cursorStyles cursorStyle = cursorStyles.down;
cursorStyle <= cursorStyles.upRestore; cursorStyle++)
{
cursors[(int)cursorStyle] = new Cursor(
assembly.GetManifestResourceStream(assemblyName.Name +
".Cursors." + cursorNames[(int)cursorStyle] + ".cur"));
}
}
The custom UseCursors
property installs and uninstalls the mouse
move handler to show just one way to do that.
[
Bindable(true),
Category("Behavior"),
DefaultValue(false),
Description("Determines whether to use orientation and position based cursors.")
]
public bool UseCursors
{
get {return useCursors;}
set
{
if(!value)
{
if(useCursors)
MouseMove -= new MouseEventHandler(OnMouseMove);
}
else
{
if(!useCursors)
MouseMove += new MouseEventHandler(OnMouseMove);
}
useCursors = value;
}
}
... and finally moving the splitter about the place using the OnSplitterMoved
event raiser...
private void OnHorizontalSplitterMoved(int newSize, int extremeSize)
{
if(SplitPosition != extremeSize)
lastPosition = SplitPosition;
OnSplitterMoved(new SplitterEventArgs(0, newSize, 0, newSize));
}
Points of Interest
It took the world a lot of time to get at something that looks like UNCOL and
it was about time! I never went the DCOM, CORBA or similar way since i.m.h.o.
it required too much plumbing on both developer as well as end user end. One
day, some years ago, after selling the company I used to work for, the answer
of my new CORBA addicted CEO to my question 'why use CORBA?' was 'It is not
from ...' you know who. Use the tools that help you best to get your work done,
whether it is from company X or company Y should not be important. I am getting
to like this .NET stuff more and more each time I juggle with it! Hope you like
it too!