Click here to Skip to main content
11,801,910 members (61,038 online)
Click here to Skip to main content

Marching Ants

, 23 Jul 2008 CPOL 36.4K 648 47
Rate this:
Please Sign up or sign in to vote.
Learn how to create marching ants easily and efficiently.


Marching ants are a common phenomenon in graphics programs that use them to show an area that has been selected by the user. Usually, this area can be a union of various shapes and even user-selected areas. This article will attempt to show you how to create your own marching ants program.


It is preferable that you know the basics of GDI+. I will attempt to show everything that you need to know to create a working program, however.

Setting Up the Selected Area

The most important part of the technique is a pair of objects: a GraphicsPath object and a Region object. Region is found in System.Drawing, and GraphicsPath is found in System.Drawing.Drawing2D. Although it is not necessary, I created a separate class where I stored my GraphicsPath and Region.

The meat of the code is right here:

public void AddRectangle(Rectangle rectangle)

public void AddCircle(Rectangle rectangle)

public void AddFreeform(Point[] points)

After initializing my GraphicsPath (_gp) and Region (_region), I have several methods for adding new shapes to them. The Region is necessary because it is the only class that can do a union of these various shapes.

Creating the Ants

The only other part of my code is the rendering code. To create the marching ants effect, I use a sneaky little trick. Normally, the GraphicsPath cannot do a union, so you would have lines from several different rectangles (instead of just the outside lines). I create a Bitmap and then fill in the center of the lines with the Region, which gets rid of all of the unnecessary lines. Then, I set the color I just filled in to be the transparent color for the Bitmap and draw it on my surface.

private void Canvas_Paint(object sender, PaintEventArgs e)
    e.Graphics.DrawImage(_image, new Rectangle(0, 0, 
                         _image.Width, _image.Height));
    //draws your image

    e.Graphics.FillRegion(new SolidBrush(Color.FromArgb(128, 0, 0, 255)), 
    //fills the selected region with 
    //a semi-transparent blue for a nice effect

    Pen pen = new Pen(Color.White, 1);
    pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
    pen.DashPattern = new float[2] { 3, 3 };
    //these lines set up a pen that will draw dashed white lines

    Bitmap ant = new Bitmap(CanvasPanel.Width, CanvasPanel.Height);
    Graphics g = Graphics.FromImage(ant);
    //creates a Graphics object from the Bitmap we will draw the ants on

    //makes the Bitmap Magenta so that the outsides will be transparent

    g.DrawPath(new Pen(Color.Black), _graphicsPath);
    g.DrawPath(pen, _graphicsPath);
    //draws a black outline (for underneath) 
    //and the dashed white line on top

    g.FillRegion(new SolidBrush(Color.Magenta), _region);
    //fills in the middle so the extra lines don't show

    //makes the areas not covered by the marching ants transparent

    e.Graphics.DrawImageUnscaled(ant, 0, 0);
    //draw the ants on to the image

Fixing the Center

Because the GraphicsPath and the Region are the same size, drawing the Region inside the GraphicsPath actually obscures some of the ants. To fix this, we can use a handy function of the GraphicsPath class - Widen. I have found that it looks best to widen 1 or 2 pixels. Here is a function that I used to fix this:

public GraphicsPath Line()
    GraphicsPath gp = new GraphicsPath();
    if (_gp.PointCount > 0)                
        //I had to add this if statement so the program 
        //wouldn't crash if my GraphicsPath was still empty
        gp.AddPath(_graphicsPath, false);
        gp.Widen(new Pen(Color.White, 2));
    return gp;

I used this function so that I wouldn't widen my original GraphicsPath object every frame or every time I added a new shape (this is an easy-to-make error that can quickly crash your program).

Animating the Ants

To animate the ants, I merely created a Timer and redrew the image at each tickCount. I am sure that there are more efficient ways to do this (such as invalidating the correct region), but for now this is simpler.

private void AntTimer_Tick(object sender, EventArgs e)
    if (_antOffset > 50) _antOffset = 0;

Then, up in the OnPaint section of the code, you need to add a line that takes this offset into effect:

pen.DashOffset = _antOffset;

Placing this code with the other code that sets the properties for your pen should give you a fully working marching ants program.

Points of Interest

Many thanks to the authors of The Secret of Marching Ants and Marching Ants Revisited. Their programs gave me some great ideas, although I think that my program is more efficient and allows for more complex paths.


This is my first article, please give me feedback Smile | :)


  • 7/14/08 - Original upload.
  • 7/23/08 - Source updated


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


About the Author

I have been coding the last several years for fun. I taught myself c# and have been enjoying it ever since.

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Maxwolf Goodliffe13-Dec-14 23:48
memberMaxwolf Goodliffe13-Dec-14 23:48 
QuestionMy vote of 5 Pin
KnolleManneke13-Feb-13 8:52
memberKnolleManneke13-Feb-13 8:52 
QuestionC++ implementation Pin
pintu_kuldip773319-Jan-12 22:05
memberpintu_kuldip773319-Jan-12 22:05 
GeneralMy vote of 5 Pin
pmorelfourrier1-Oct-11 10:54
memberpmorelfourrier1-Oct-11 10:54 
General_graphicsPath Pin
agriweb21-Sep-09 10:56
memberagriweb21-Sep-09 10:56 
QuestionImage Transition and other issues Pin
Member 380027024-Apr-09 1:43
memberMember 380027024-Apr-09 1:43 
GeneralSource Code Pin
bfd31-Jul-08 6:08
memberbfd31-Jul-08 6:08 
GeneralVery Nice Pin
Paul Conrad26-Jul-08 16:39
memberPaul Conrad26-Jul-08 16:39 
GeneralSource Code Pin
Hax0r77815-Jul-08 5:22
memberHax0r77815-Jul-08 5:22 
GeneralRe: Source Code Pin
sam.hill15-Jul-08 19:06
membersam.hill15-Jul-08 19:06 
GeneralRe: Source Code Pin
strictly8616-Jul-08 0:27
memberstrictly8616-Jul-08 0:27 
GeneralRe: Source Code Pin
Hax0r77822-Jul-08 19:59
memberHax0r77822-Jul-08 19:59 
GeneralRe: Source Code Pin
Teashirt225-Jul-08 7:38
memberTeashirt225-Jul-08 7:38 
Generalgood Pin
Aamir Mustafa14-Jul-08 7:26
memberAamir Mustafa14-Jul-08 7:26 
QuestionWhere is the source code? Pin
TBermudez14-Jul-08 4:25
memberTBermudez14-Jul-08 4:25 
GeneralGood job Pin
strictly8613-Jul-08 22:39
memberstrictly8613-Jul-08 22:39 
GeneralAwesome Pin
JRSofty13-Jul-08 21:51
memberJRSofty13-Jul-08 21:51 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.151002.1 | Last Updated 23 Jul 2008
Article Copyright 2008 by Hax0r778
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid