The HotSpot control constitutes a set of irregularly shaped visual elements acting as multi-state buttons. Each of these visual elements may have several states. Every state is characterized by its own image representation. Left mouse button click on a particular element leads to its transition from one state to another. Such a transition is depicted by change of element’s image from a picture corresponded to initial state to a picture corresponded to a new state. Click on a particular element may change not just state of this element but also state of some other elements, according to predefined rules. Control’s container (parent) should be notified on event of state transition.
The control may be also dynamic. That is, control’s visual elements are able to move and/or be reshaped versus time according to predefined rules. This modification is not caused by change in element’s state. Dynamic visual element has different positions/images corresponding to the same state.
In this article, we present base hot spot control classes that allow developer to easily define rules for both state transition and dynamics, and provide simple mechanism for parent notification. Code is written in C#.
How to Use?
Two base classes for hot spot control objects are designed. The first one,
HotSpotControl (derived from
UserControl .NET framework class), contains a set of static multi-state visual elements. The second one,
DynamicHotSpotControl (derived from
HotSpotControl), incorporates dynamics permitting visual elements to change their shape and position.
HotSpotLib assembly contains these classes as well as other support classes and interfaces. The assembly consists of two files, namely, HotSpotLib.dll and DynamicHotSpotLib.netmodule. The former contains code for static hot spot control, whereas the letter supports “dynamic extension” classes. The DLL file contains an assembly manifest. If your application is confined with just static hot spot control, then the NETMODULE file need not be deployed to an end user (although it is needed to get application built).
DynamicHotSpot control, the following steps have to be performed.
DynamicHotSpotLib namespaces are added to the References section of the project.
- A new
MyDynamicHotSpotControl class is derived from
public class MyDynamicHotSpotControl :
DynamicHotSpotControl, IHotSpotChangeState, IDynamicHotSpot
IHotSpotChangeState defines the following method to be implemented.
void ChangeStateRules() – this method defines transition between states for each visual element of a control. Normally, it uses
HitVisualElement property of
HotSpotControl to determine visual element clicked by left mouse button. The property returns reference to object of
VisualElement class. References to
VisualElement objects of the control may be obtained with
HotSpotControl’s name or id (serial number) indexers. Similarly,
VisualElement class provides the name and id indexers to get references to its
State objects. The
CurrentState property of
VisualElement class allows a developer to set/get current element state.
In the sample below, two visual elements, “
Beetle” and “
Ground”, have two states (
1) each. Left mouse button click on “
Beetle” alternates states of both elements. Click on "
Ground" causes change of state only for clicked element.
public void ChangeStateRules()
if (null != HitVisualElement)
HitVisualElement.CurrentState = (HitVisualElement.CurrentState + 1) % 2;
if ("Beetle" == HitVisualElement.Name)
this["Ground"].CurrentState = (this["Ground"].CurrentState + 1) % 2;
- The following
virtual methods may be overridden (optionally).
void OnChangeState()– This method defines actions to be taken by control when one of its visual elements is clicked. It may be possible that no action has to be taken (default implementation) since a parent of a control is notified separately with event/delegate mechanism (see below).
string ConstructTip(string visualElementName, string stateName) – This method constructs tip for an element located currently under cursor. “Bricks” for such a construction are name of visual element and name of its current state. If method returns empty
string, then no tip is shown. Default implementation returns name of visual element.
IDynamicHotSpot defines the following method to be implemented.
void DynamicsRules() – This method defines rules for movement of visual element. It is called once on each timer tick by underlying
DynamicHotSpotControl object. The sample of the method’s implementations for reciprocate movement of two objects may be found below:
private int step = 2;
public void DynamicsRules()
if (0 == TimerTicksCount)
step = -step;
this["Beetle"].X += step;
this["Ground"].X -= step;
In this sample,
protected get-only property
DynamicHotSpotControl class is used to synchronize objects movement.
- Constructor of
MyDynamicHotSpotControl class is designed to create all visual elements of control and all states of each visual element. It takes two integer parameters related to control dynamics. The first parameter defines time interval between the two adjacent timer ticks (i.e., timer sampling interval, in ms). The second parameter defines threshold value for timer ticks count. Timer ticks count is reset to zero after it exceeded the threshold. Constructor calls constructor of base class
DynamicHotSpotControl passing parameters on to it. The sample of
MyDynamicHotSpotControl constructor is given below:
public MyDynamicHotSpotControl(int timerInterval, int timerClicksCountMax)
: base(timerInterval, timerClicksCountMax)
IHotSpotChangeStateImpl = this;
IDynamicHotSpotImpl = this;
string resourceDir = "res\\";
ActiveCursorFileName = resourceDir + "Hand.cur";
VisualElement ve0 = AddVisualElement("Ground", new Point(15, 0));
ve0.AddState("Green", resourceDir + "Ground0", "bmp");
ve0.AddState("Cyan", resourceDir + "Ground1", "bmp");
VisualElement ve1 = AddVisualElement("Beetle", new Point(30, 0));
ve1.AddState("Image", resourceDir + "BeetleImage", "bmp");
ve1.AddState("Text", resourceDir + "BeetleText", "bmp");
References to implementation of
IDynamicHotSpot interfaces need to be passed to ancestor object. This is carried out using
IHotSpotChangeStateImpl = this;
IDynamicHotSpotImpl = this;
Cursor changes its shape when left mouse button is gone down on a visual element. New cursor shape is set with
ActiveCursorFileName property. Method
AddVisualElement() creates new visual element using its name and location point as parameters. Methods
VisualElement class creates a new state for visual element based on the state name, picture file name and picture file extension. The method finds all picture files named according to the following rule:
"picture file name" + "_" + i.ToString() ,
i – integer serial number. All these files are loaded, and their pictures are displayed on timer tick producing animated image of visual object for each of its state.
- The above picture files are prepared and placed in the proper path.
- Paragraphs 2 through 7 dealt with customized
MyDynamicHotSpotControl derived from
DynamicHotSpotControl. This paragraph describes code that should be added to the control’s parent form. A new control will be created and its properties initialized probably in the parent’s constructor. At this point, a handler to the
HotSpotEvent is added. This event is fired when left mouse button moves down and up on the same visual element (element is clicked). Delegate for the event handler is defined in class
HotSpotControl. It takes two parameters: reference to
HotSpotControl object (source of event), and standard
EventArgs. Sample showing a fragment of parent’s constructor code is listed below:
MyDynamicHotSpotControl myDynamicHotSpotCtrl =
new MyDynamicHotSpotControl(500, 60);
myDynamicHotSpotCtrl.Name = "DYNAMIC HotSpot";
myDynamicHotSpotCtrl.Dock = DockStyle.Top;
myDynamicHotSpotCtrl.Size = new Size(0x50, 0x50);
The above procedure is addressed to dynamic hot spot control. Usage of static version is easier. In this case, customized control is derived from
HotSpotControl class and implements only
DynamicHotSpotLib namespace is not used, and
IDynamicHotSpot interface is not implemented. Each state of a particular visual element is characterized by just one picture. Examples of usage of both static and dynamic version of the control may be found in file Form1.cs of accompanied sample code.
Foundation of hot spot control is implemented with three classes:
HotSpotControl. Actual customized control has to be derived from
HotSpotControl class and
IHotSpotChangeState interface implementing method
State characterizes each state of visual element. It contains parameters like name, id and pictures (original picture and the same picture with transparent background). Method
State class checks whether mouse click was performed on non-transparent area of its picture.
VisualElement defines each visual element of the control.
ArrayList alState of all states of a visual element. These states are accessible outside the class through id and name indexers.
AddState() allows developer to create a new
State object and add it to
AddState() method uses internally virtual protected
StateFactory() method to create either
State object or object of
State-derived class. Method
HitTest() checks whether visual object was mouse clicked. For this, it relies on
HitTest() method of current state of the visual element. Method
Draw() is responsible for drawing of visual element in its current state.
HotSpotControl is derived from standard .NET
UserControl class. It serves as base for customized hot spot control class, or, alternatively for
DynamicHotSpotControl class. Not surprisingly,
ArrayList alVisualElement of all visual elements of the control. Id and name indexers expose visual elements to outside world.
HotSpotControl handles down, up and move mouse events. It performs hit test and draws its visual elements - both by looping through its
alVisualElement list of visual elements.
Virtual protected methods of the class and some of its
public properties are discussed in the “How to Use?” section.
HotSpotControl defines event
HotSpotEvent and appropriate delegate
HotSpotEventHandler. This event is fired when visual element is clicked, i.e., left mouse button went down and up on the same visual element. It is assumed that control’s parent form provides implementation for the delegate.
Foundation of dynamic hot spot control is implemented with three classes:
MultipictureState (derived from
MultipictureVisualElement (derived from
VisualElement class) and
DynamicHotSpotControl (derived from
HotSpotControl). Actual control customized by developer has to be derived from
IDynamicHotSpot interfaces implementing methods
DynamicsRules() of these interfaces.
Unlike static version, in dynamic hot spot control visual elements are presented with “animated” graphic images being in the same state. To support this feature, class
MultipictureState accommodates several pictures, and class
DynamicHotSpotControl implements timer mechanism. Class
MultipictureState has a
PictureContext (containing original picture, the same picture with transparent background and background color) and
ArrayList alPictureContext of all picture contexts for this state.
Code sample consists of the following files. File HotSpot.cs contains the
HotSpotControl related classes (
HotSpotLib namespace) and will be compiled to HotSpotLib.dll. File DynamicHotSpot.cs contains the
DynamicHotSpotControl related classes (
DynamicHotSpotLib namespace) and will be compiled to DynamicHotSpotLib.netmodule. Files HotSpotLib.dll (containing assembly manifest) and DynamicHotSpotLib.netmodule form HotSpotLib assembly. File Form1.cs contains sample of code consuming the controls. It will be compiled to TestHotSpot.exe file. File RunMe.bat provides compilation and runs the test. TestHotSpot.exe is executable for the sample. Test form containing dynamic and static hot spot controls is depicted below:
In the sample,
Form1 accommodates two hot spot controls, one dynamic and one static. Each control contains three visual elements: “
Ground” and “
Blot”. Tip related to a “
Ground” visual element of a dynamic control is seen (although cursor located just over upper-left corner of tip area is not captured). Click on each of visual elements leads to change in the elements’ state according to rules defined in customized control. Static control is permanently docked to the bottom, whereas dynamic control allows docking – again, according to rules defined by control customization. In response to left mouse button click on a visual element, a control repaints all its visual elements in their new states and displays two message boxes successively. The first one is emitted by customized control, and the second one indicates call of the control’s parent change state event handler. To change docking position of the dynamic control, user should press left mouse button over any visual element and release the button elsewhere.
Improvements and Further Development
Hot spot control presented may be improved in different ways. It may be useful in some cases to handle situation when mouse button is pressed over one visual element and released over another. Drag-and-drop operation for visual elements within one control, or even between the controls may be supported.
Dynamics could be improved by avoiding blinking effect while repaint (well known problem which should be addressed separately), more sophisticated dynamic transformation of pictures (e.g., rotation). Adding ability to play animated GIF files is also useful.
These hot spot controls may also serve as a base and departure point for development of other types of .NET controls, like for instance, customizable toolbar control.
Static and dynamic versions of .NET hot spot control have been developed. Its images act as multi-state buttons. Rules for states transition and dynamics are easily customizable. With some improvements and modifications, the control may serve as base for other controls classes.
I'd like to express my gratitude to Stas Levin, a Windows GUI development expert (BCGSoft) and charming Irina Zherdenovsky (Creo) for useful professional discussion.