Click here to Skip to main content
Click here to Skip to main content

C# Windows Forms ImageMap Control

By , 31 Aug 2002
 

Mouse hovering on red polygon  Mouse clicked on white rectangle

Introduction

I noticed a few requests on various newsgroups for an image map control which could be used in a Windows Forms application. I had not worked much with the System.Drawing namespace, so I decided to give it a try. This control is the result.

How It Works

The control uses a standard PictureBox control internally, specifically it's ability to load and display an image as well as it's inherited MouseMove, MouseLeave, and Click events. A ToolTip component is used as well to display tooltips for defined regions. Currently, the key specified for a region is used for the tooltip text, though it would be pretty easy to allow an additional "tooltip" property to be assigned for each region.

The bulk of the logic is in the private getActiveIndexAtPoint method shown below. The method is called whenever the mouse moves within the control to determine which region, if any, the mouse is within. If the mouse is within a region, the region's index is returned by the method. This index is used to lookup the region's key, which is then used to set the text displayed by the tooltip. The cursor is also changed to a hand and the index is stored in a private property to be re-used if the mouse is clicked, avoiding the necessity to call this method again. If the method does not find a region, a -1 is returned and the cursor is set to it's default.

private int getActiveIndexAtPoint(Point point)
{
    System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
    System.Drawing.Drawing2D.GraphicsPathIterator iterator = 
                new System.Drawing.Drawing2D.GraphicsPathIterator(_pathData);
    iterator.Rewind();
    for(int current=0; current < iterator.SubpathCount; current++)
    {
        iterator.NextMarker(path);
        if(path.IsVisible(point, this._graphics))
            return current;
    }
    return -1;
}

How To Use It

You can add this control to your toolbox just as you would any other .NET control. Once, added, simply drag-and-drop an instance of the control onto your form. Use the Image property to assign the desired image to the control.

Once you've added the control to your form, you can begin to call the various Add- methods to define the "hot-spots" within your image. The available methods are AddEllipse, AddRectangle, and AddPolygon. I tried to follow the conventions of HTML image maps with respect to defining the various shapes, and I overloaded the AddElipse and AddRectangle methods to accept ".NET-friendly" types such as Point and Rectangle. Since the methods follow the convention of HTML image maps, you should be able to use any existing image map generation software to determine exactly what points to specify for the desired regions within your image.

Here is the code required to define an HTML image map using the image in the first screenshot:

<!--Text BUTTON-->
   <area shape="rect" coords="140,20,280,60">

<!--Triangle BUTTON-->
   <area shape="poly" coords="100,100,180,80,200,140">

<!--Face BUTTON-->
   <area shape="circle" coords="80,100,60">

Here are the equivalent regions defined using this control:

this.imageMap1.AddRectangle("Rectangle", 140, 20, 280, 60);
this.imageMap1.AddPolygon("Polygon", new Point[] {new Point(100, 100), 
                          new Point(180, 80), new Point(200, 140)});
this.imageMap1.AddElipse("Ellipse", 80, 100, 60);

The control will raise an event - RegionClick - whenever the mouse is clicked within a defined region. The event passes two values denoting the index and the key of the clicked region. You would then take whatever action you wished based on the region clicked.

That's it! I hope this meets the needs of those who had requested an image map control for use in a Windows Forms application. Comments and requests are welcome.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Ryan LaNeve
Web Developer
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerAdding RegionMouseMove and RegionChanged Eventsmemberajorani22 Jan '13 - 20:07 
I have implemented these events. Here's the code for ImageMap.cs:
 
 
        private int _lastActiveIndex = -1;
 
        public delegate void RegionMouseMoveDelegate(int index, string key, 
                                                  System.Windows.Forms.MouseEventArgs e);
        [Category("Mouse")]
        public event RegionMouseMoveDelegate RegionMouseMove;
 
        public delegate void RegionChangedDelegate(int index, string key, int lastIndex, 
                                                   System.Windows.Forms.MouseEventArgs e);
        [Category("Mouse")]
        public event RegionChangedDelegate RegionChanged;
 

private void pictureBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
    int newIndex = this.getActiveIndexAtPoint(new Point(e.X, e.Y));
    if(newIndex > -1)
    {
	pictureBox.Cursor = Cursors.Hand;
	if(this._activeIndex != newIndex)
		this._toolTip.SetToolTip(this.pictureBox,   
                    this._pathsArray[newIndex].ToString());
    }
    else
    { 
	pictureBox.Cursor = Cursors.Default;
	this._toolTip.RemoveAll();
    }
    this._lastActiveIndex = this._activeIndex;
    this._activeIndex = newIndex;
 

    if (this._activeIndex > -1 && this.RegionMouseMove != null)
            this.RegionMouseMove(this._activeIndex, 
                  this._pathsArray[this._activeIndex].ToString(), e);
 
    if (this._activeIndex != this._lastActiveIndex && this.RegionChanged != null)
    {
        string key = null;
        if (this._activeIndex > -1)
        {
            key = this._pathsArray[this._activeIndex].ToString();
        }
        this.RegionChanged(this._activeIndex, key, this._lastActiveIndex, e);
    }
}
 

private void pictureBox_MouseLeave(object sender, System.EventArgs e)
{
   this._lastActiveIndex = this._activeIndex;
   this._activeIndex = -1;
   this.Cursor = Cursors.Default;
}
 

 
BTW nice control !
QuestionMouse Leave on imageMapmemberczarownica1022 Oct '12 - 3:02 
Hello,
 
I have one problem.
 
I want to change background image of the Form1, when mouse is moving out of Form1.
It should work like that:
When app starts it's only logo of corporation.
When you move mouse over it, background changes to logo with some arreas with labels (I've made imageMap covering them, to add click-on-regions).
When you move mouse out of logo, it's changing again to simple logo.
 
I've made panel1 with simple logo all over the Form1, and added MouseMove that makes it invisible and logo with labels is displayed. And of course, all click-on-regions work perfectly.
But, I don't know how to make it, to show panel1 again, when you move mouse out of Form1.
I've tried to add MouseLeave at Form1 and imageMap1, but it doesn't work Frown | :(
 
Please, help me Smile | :)
 
Iwona (Poland)
QuestionCompact Framework 3.5...possible?memberMember 81340339 Aug '11 - 4:52 
Hi guys,
Would it be possible to translate it into CE?
how can it be possible? (where do yous suggest I should start to do that?)
 
Thanks in advance! :-PoKo-:
GeneralWhat nice workmemberMember 81340333 Aug '11 - 9:24 
just what I needed Big Grin | :-D thank you
GeneralAbout Licensingmembercharudatt.p@zensar.com26 Jan '10 - 18:30 
Hi,
 
I am working on a C# Windows Application, it is a touch screen application and will be used for recording production of sanitary wares. Here in one screen we are having facility of fault recording with its location, to implement the same I found the control suitable. I would like to know whether I can use the control in my code or not? Is there any license needed to use it?
 

Regards,
GeneralRe: About LicensingmemberRyan LaNeve26 Jan '10 - 18:49 
Feel free to use however you like.
 
Ryan LaNeve
www.laneve.com[^]

GeneralNeeds Work (Here is an updated version people)memberMember 219148521 May '09 - 8:22 
This control is okay. But it could be much better. For starters, it doesn't need to be a UserControl. It should simply inherit from PictureBox instead. By making it a UserControl and hiding a PictureBox control inside it you made it more complex than it needs to be and you killed the ability for the user implement outlining or fill effects by drawing on the control surface (since the user can't get at the hidden PictureBox which is where the drawing needs to take place). Also, the index parameter is useless because you haven't exposed any properties on the UserControl to allow to the user to do anything useful with the index (like fetch an array of points for the selected Region).
 
I've adjusted the code. With this variation on the control you can not use the GetPath to fetch the GraphicsPath for the selected region via the index. With the GraphicsPath for the selected region users can now do hovering effects, outline effects, etc...
 
Here's the code:
 
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
 
namespace DotNetOpenSource.Controls
{
    /// <summary>
    /// Summary description for ImageMap.
    /// </summary>
    [ToolboxBitmap(typeof (ImageMap))]
    public class ImageMap : PictureBox
    {
        private GraphicsPath _pathData;
        private int _activeIndex = -1;
        private ArrayList _pathsArray;
        private ToolTip _toolTip;
 
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private Container components;
 
        public delegate void RegionClickDelegate(int index, string key);
 
        [Category("Action")]
        public event RegionClickDelegate RegionClick;
 
        public ImageMap()
        {
            _pathsArray = new ArrayList();
            _pathData = new GraphicsPath();
            _pathData.FillMode = FillMode.Winding;
 
            components = new Container();
            _toolTip = new ToolTip(components);
            _toolTip.AutoPopDelay = 5000;
            _toolTip.InitialDelay = 1000;
            _toolTip.ReshowDelay = 500;
        }
 

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }
            base.Dispose(disposing);
        }
 

        public int AddElipse(string key, Point center, int radius)
        {
            return AddElipse(key, center.X, center.Y, radius);
        }
 
        public int AddElipse(string key, int x, int y, int radius)
        {
            if (_pathsArray.Count >

GeneralRe: Needs Work (Here is an updated version people)memberDan Troesser1 Sep '09 - 11:23 
Hello,
 
Thanks for the post. Not all of your code was posted, however. Can you post the rest?
 
Thanks,
 
-Dan
GeneralRe: Needs Work (Here is an updated version people)memberMember 23454648 Mar '12 - 21:43 
Would it be possible to get the entire code. Only part of it is visbile here, and I would really be interested in the changes you made.
 
Thanks
GeneralI want draw more than one circle , arrow or ellipse on imagemembersushilabhanvar26 Apr '09 - 19:29 
Hi friends,,

I am working on c# desktop Application in which I want image editor functionality like I have image and on it I want draw circle rectangle ,arrow and ellipse . I am able to draw it but only once at a time . if i select circle than i cant draw circle more than one and other also like rectangle ,arrow
. for this I took refrence of cropcircle test application.

on mouse down that is replacing previus value to new . how can i REMOVE THIS PROBLEM....
SUGGEST me any test application.
GeneralThanks!membertrempnvt19 Mar '09 - 0:33 
This took me a little while to figure out, but it works great.
GeneralColour in hotspotsmemberAxell14 Feb '09 - 0:42 
I would also like to know how to colour the hotspots when mouse over. Is it possible?
GeneralWant Image Editor Source code in C# windows application whose work like MS Paintmemberdheeraj.mittal24 Nov '08 - 4:20 
Hi.
 
I am developing a windows application in C#.
 
I want the source code of Image Editor in C# windows application whose work like MS Paint. on which we can
 
write text on image dynamically through mouse drag and drop. also we can drag other controls like arrow or box.
 

 
thanks in advance
 
dhemittal@gmail.com
GeneralNeed some inputs for GraphicsPath.IsVisible(point pt) methodmemberkritti1026 Jun '08 - 22:36 
I am using GraphicsPath.IsVisible(point pt) method to find if the point of click is withing the region or not. However when I am using it in run time application, the method is behaving correctly but when using the same method in design time application, though the point lies inside the GraphicsPath region is returns false.
 
Is there any limitaion with the IsVisible method that it can't be used in design time.
 
any response to this will be highly appreciated.
 
Thanks in advance.
GeneralGurumemberutehn29 Mar '07 - 1:06 
if you have more than 1 Rectangle, Is not work on my pc.
 
I hope someone is help me....
 
Thank you

QuestionWhat if resize?memberhuyhk12 Feb '07 - 16:57 
Nice work!
But can we resize the regions if the form resized?

GeneralAwesomememberonnadi315 Nov '06 - 22:10 
Dawg. This control is very awesome.
 
By the way, in your article, could you explain how to register the event handler for RegionClick? I was able to do it eventually, but I could not find how you did it from the sample code.
 
Ogechi Nnadi.
GeneralHimemberpannujagwinder6 Oct '06 - 10:00 
this code is very helpful ! but i tried this example by changing the image and then i tried adding a rectangle to tht image programmatically on mouse events it adds the rectangle but the rectangle is not visible.... is there any way to assign color to rectangle just the boudary so tht it would be visible...how do i do that?
 
any kind of help is welcome!
 
Thanks
PannuSmile | :)
QuestionWhat about hover color?membermackles14 Jul '06 - 12:03 
How would I implement a hover color to these regions?
AnswerRe: What about hover color?memberMember 44219792 Oct '08 - 4:01 
That's a good question. I hope we get a good answer for it.Confused | :confused:
GeneralImage Mapper -memberchuck crego7 Jul '06 - 5:41 
Ryan,
 
While working on a medical imaging app, requiring a method of determining the location where a user clicked on an image, I came across your Image Map control.
 
Since the control allows one to select a particular body part, the control is exactly what I was trying to create (for me, "the sledge hammer and a pea" approach).
 
Anyway, thank you very much for your ingenuity and generosity.
 
Sincerely,
 
Chuck Crego
RTSI - Fort Myers, FL
QuestionNo Controlmemberalainrod27 May '06 - 18:31 
Is there a way to make this work by putting the code directly in the form instead of a component?
 
Greetings,
 
Alain Rodriguez

AnswerRe: No ControlmemberShof12 Aug '06 - 16:36 
Why, what is the problem with it being a control?
GeneralModified RemoveRegions()memberMoongster5 Feb '06 - 21:39 
I've modified the RemoveRegions() method to reset the GraphicsPath. This allows me to redefine the hotspots when the application displays another picture on the same form.
 

public void RemoveRegions()
{
this._pathsArray.Clear();
this._pathData.Reset();
}

GeneralGreat Work!memberHero Lala2 Dec '05 - 19:35 
Hi,
 
I am impressed by your code. I am still a student of C# and trying to learn as much as possible.
 
Is there any way that one can extend this code to include mouseHover over regions?
 
Thanks!

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 1 Sep 2002
Article Copyright 2002 by Ryan LaNeve
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid