Use a rubber band box to let the user select an area in a picture in C#

When the program starts, it saves the PictureBox's original image. It also sets KeyPreview to true so the form's KeyPress event can detect Escape key presses and cancel area selection.

private Bitmap m_OriginalImage = null;
private int m_X0 = -1;
private int m_Y0 = -1;
private int m_X1 = -1;
private int m_Y1 = -1;
private bool m_SelectingArea = false;
private Bitmap m_SelectedImage = null;
private Graphics m_SelectedGraphics = null;

// Save the original image.
private void Form1_Load(object sender, EventArgs e)
{
m_OriginalImage = new Bitmap(picImage.Image);

this.KeyPreview = true;
}

Drawing a rubber band box has three steps controlled by three event handlers: MouseDown, MouseMove, and MouseUp.

When the user presses the mouse down on the picture, the MouseDown event handler starts selecting an area.

// Start selecting an area.
private void picImage_MouseDown(object sender, MouseEventArgs e)
{
// Save the starting point.
m_SelectingArea = true;
m_X0 = e.X;
m_Y0 = e.Y;

// Make the selected image.
m_SelectedImage = new Bitmap(m_OriginalImage);
m_SelectedGraphics = Graphics.FromImage(m_SelectedImage);
picImage.Image = m_SelectedImage;
}

This code sets m_SelectingArea to true so the program knows it is selecting an area. It then saves the mouse's current coordinates and makes a copy of the PictureBox's original image. It also makes the PictureBox display this new image m_SelectedImage. Later the MouseMove event handler will use the associated Graphics object m_SelectedGraphics to draw the rubber band box.

When the user moves the mouse over the picture, the MouseMove event handler continues selecting the area.

// Continue selecting an area.
private void picImage_MouseMove(object sender, MouseEventArgs e)
{
// Do nothing if we're not selecting an area.
if (!m_SelectingArea) return;

// Generate the new image with the selection rectangle.
m_X1 = e.X;
m_Y1 = e.Y;

// Copy the original image.
m_SelectedGraphics.DrawImage(m_OriginalImage, 0, 0);

// Draw the selection rectangle.
using (Pen select_pen = new Pen(Color.Red))
{
select_pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
Rectangle rect = MakeRectangle(m_X0, m_Y0, m_X1, m_Y1);
m_SelectedGraphics.DrawRectangle(select_pen, rect);
}

picImage.Refresh();
}

First, if the program isn't currently selecting an area, the event handler exits.

Next the code saves the mouse's new location. It copies the original image onto the m_SelectedImage to erase the previous rubber band box. Finally the code draws a new rubber band box with a red dashed pen.

The following code shows how the MakeRectangle function converts the mouse's initial and current positions into a Rectangle.

// Return a Rectangle with these points as corners.
private Rectangle MakeRectangle(int x0, int y0, int x1, int y1)
{
return new Rectangle(
Math.Min(x0, x1),
Math.Min(y0, y1),
Math.Abs(x0 - x1),
Math.Abs(y0 - y1));
}

When the user releases the mouse, the MouseUp event handler finishes selecting the area.

// Finish selecting the area.
private void picImage_MouseUp(object sender, MouseEventArgs e)
{
// Do nothing if we're not selecting an area.
if (!m_SelectingArea) return;
m_SelectingArea = false;

// Stop selecting.
m_SelectedImage = null;
m_SelectedGraphics = null;
picImage.Image = m_OriginalImage;
picImage.Refresh();

// Convert the points into a Rectangle.
Rectangle rect = MakeRectangle(m_X0, m_Y0, m_X1, m_Y1);
if ((rect.Width > 0) && (rect.Height > 0))
{
// Display the Rectangle.
MessageBox.Show(rect.ToString());
}
}

Again the code checks whether the program is selecting an area and exits if it is not.

The program then sets m_SelectingArea to false so future mouse movement is ignored. The code restores the PictureBox's original image and refreshes it.

The event handler finishes by converting the selected points into a Rectangle and displaying it's properties. In my next blog entry, I'll explain how to do something more interesting with the selected area: copy that part of the image to the clipboard.

The final piece of code is the form's KeyPress event handler. If the user presses Escape, the code cancels the current area selection.

// If the user presses Escape, cancel.
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 27)
{
if (!m_SelectingArea) return;
m_SelectingArea = false;

// Stop selecting.
m_SelectedImage = null;
m_SelectedGraphics = null;
picImage.Image = m_OriginalImage;
picImage.Refresh();
}
}

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments

Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.