Click here to Skip to main content
15,879,002 members
Articles / Programming Languages / C#

The Hot Spot .NET Control

Rate me:
Please Sign up or sign in to vote.
4.76/5 (26 votes)
31 Aug 2002CPOL10 min read 136.2K   2.5K   63   1
A control contains a set of [animated] pictures acting as multi-state buttons

Abstract

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).

To use DynamicHotSpot control, the following steps have to be performed.

  1. HotSpotLib and DynamicHotSpotLib namespaces are added to the References section of the project.
    C#
    using HotSpotLib;
    using DynamicHotSpotLib; 
  2. A new MyDynamicHotSpotControl class is derived from DynamicHotSpotControl. MyDynamicHotSpotControl implements IHotSpotChangeState and IDynamicHotSpot interfaces.
    C#
    public class MyDynamicHotSpotControl : 
                           DynamicHotSpotControl, IHotSpotChangeState, IDynamicHotSpot
  3. Interface 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 (0 and 1) each. Left mouse button click on “Beetle” alternates states of both elements. Click on "Ground" causes change of state only for clicked element.

    C#
    public void ChangeStateRules() 
    {
        if (null != HitVisualElement)
        {
            HitVisualElement.CurrentState = (HitVisualElement.CurrentState + 1) % 2;
            if ("Beetle" == HitVisualElement.Name)
                this["Ground"].CurrentState = (this["Ground"].CurrentState + 1) % 2;
        }
    }
  4. 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.
  5. Interface 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:
      C#
      private int step = 2;     // in pixels
      
      public void DynamicsRules()
      {
          // Rules of dynamic changes
          if (0 == TimerTicksCount)
              step = -step;
      
          // Movements
          this["Beetle"].X += step;
          this["Ground"].X -= step;
      }

      In this sample, protected get-only property TimerTicksCount of DynamicHotSpotControl class is used to synchronize objects movement.

  6. 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:
    C#
    public MyDynamicHotSpotControl(int timerInterval, int timerClicksCountMax) 
                : base(timerInterval, timerClicksCountMax)
    {
        IHotSpotChangeStateImpl = this;
        IDynamicHotSpotImpl = this;
    
        string resourceDir = "res\\";
        ActiveCursorFileName = resourceDir + "Hand.cur";
    
        // "Ground" Visual Element
        VisualElement ve0 = AddVisualElement("Ground", new Point(15, 0));
        ve0.AddState("Green", resourceDir + "Ground0", "bmp");
        ve0.AddState("Cyan",  resourceDir + "Ground1", "bmp");
    
        // "Beetle" Visual Element
        VisualElement ve1 = AddVisualElement("Beetle", new Point(30, 0));
        ve1.AddState("Image", resourceDir + "BeetleImage", "bmp");
        ve1.AddState("Text",  resourceDir + "BeetleText", "bmp");
    }

    References to implementation of IHotSpotChangeState and IDynamicHotSpot interfaces need to be passed to ancestor object. This is carried out using protected set-only IHotSpotChangeStateImpl and IDynamicHotSpotImpl properties:

    C#
    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 AddState() of 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:

    C#
    "picture file name" + "_" + i.ToString() ,

    where 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.

  7. The above picture files are prepared and placed in the proper path.
     
  8. 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:
    C#
    // Dynamic HotSpot Control
    MyDynamicHotSpotControl myDynamicHotSpotCtrl = 
                                    new MyDynamicHotSpotControl(500, 60);
    myDynamicHotSpotCtrl.Name = "DYNAMIC HotSpot";
    myDynamicHotSpotCtrl.Dock = DockStyle.Top;
    myDynamicHotSpotCtrl.Size = new Size(0x50, 0x50);
    
    // Add event handler
    myDynamicHotSpotCtrl.HotSpotEvent += 
                              new HotSpotControl.HotSpotEventHandler(OnHotSpot);	
    
    Controls.Add(myDynamicHotSpotCtrl);

    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 IHotSpotChangeState interface. 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.

What’s Inside?

Foundation of hot spot control is implemented with three classes: State, VisualElement and HotSpotControl. Actual customized control has to be derived from HotSpotControl class and IHotSpotChangeState interface implementing method ChangeStateRules() of IHotSpotChangeState interface.

Class 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 HitTest() of State class checks whether mouse click was performed on non-transparent area of its picture.

Class VisualElement defines each visual element of the control. VisualElement contains ArrayList alState of all states of a visual element. These states are accessible outside the class through id and name indexers. Public method AddState() allows developer to create a new State object and add it to alState list. 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.

Class 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, HotSpotControl contains 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 State class), MultipictureVisualElement (derived from VisualElement class) and DynamicHotSpotControl (derived from HotSpotControl). Actual control customized by developer has to be derived from HotSpotControl class, IHotSpotChangeState and IDynamicHotSpot interfaces implementing methods ChangeStateRules() and 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 private class 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

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:

Sample Image

In the sample, Form1 accommodates two hot spot controls, one dynamic and one static. Each control contains three visual elements: “Beetle”, “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.

Conclusion

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.

Thanks

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Israel Israel


  • Nov 2010: Code Project Contests - Windows Azure Apps - Winner
  • Feb 2011: Code Project Contests - Windows Azure Apps - Grand Prize Winner



Comments and Discussions

 
GeneralFlag of Bangladesh Pin
Maruf Maniruzzaman9-Mar-08 20:12
Maruf Maniruzzaman9-Mar-08 20:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.