Managed C++: Rubber-Banding and Cropping Images

My previous article illustrated how to load, display, and dynamically resize images. This article demonstrates how to allow a user to select an area of an image with their mouse (sometimes called rubber-banding) and crop the image to that selected region.

Step-by-Step Instructions

Define the form-level members

First, define the variables that will be used to control how and where the rectangle is drawn. The cropRect defines the exact coordinates of the cropped image (the x and y coordinates as well as the width and height). Use the cropping boolean value to determine when the user has the mouse button down so that the user doesn't draw a rectangle when he or she simply is moving the mouse across the image. Finally, use the cropOriginX and cropOriginY to determine the original starting position (You'll see why these values need to be stored separately from the cropRect member shortly.):

public __gc class Form1 : public System::Windows::Forms::Form
  Rectangle cropRect;
  bool cropping;
  int cropOriginX, cropOriginY;


Implement an event handle for the PictureBox control's MouseDown event

The user pressing the mouse button constitutes the start of a new rectangle. The first thing to verify is that an image file has been loaded. The PictureBox control has a member called Image that represents the image being displayed, so the code can easily check for its existence in a boolean statement. If an image is being displayed, the method first calls the PictureBox::Refresh method to remove the previously drawn rectangle. If you're familiar with the famous MFC Scribble example application, you'll recall that to erase the rectangle, it simply drew the rectangle using the client area background color. However, that obviously won't work here because the program has drawn on an image (instead of a simple blank background). Therefore, the quickest and easiest way to remove the previous rectangle is by refreshing the image.

Once the image has been refreshed, the method needs only to initialize the variables that define where the rectangle is drawn and set a boolean flag to indicate that the user is currently cropping the image:

private: System::Void picImage_MouseDown(System::Object * sender,
                                         MouseEventArgs *  e)
  if (picImage->Image)

    cropOriginX     = e->X;;
    cropRect.X      = e->X;
    cropRect.Height = 0;

    cropOriginY    = e->Y;
    cropRect.Y     = e->Y;
    cropRect.Width = 0;

    cropping = true;

Implement an event handle for the PictureBox control's MouseMove event

As you might imagine, this is where most of the action occurs. The mousemove method first verifies that the user is cropping the image. If so, it refreshes the image (to erase any pre-existing rectangle), calls SetCroppingRectangle (to properly set up the rectangle to be drawn), and then calls the PictureBox::Invalidate method to cause the picture box to be repainted:

private: System::Void picImage_MouseMove(System::Object * sender,
                                         MouseEventArgs *  e)
  if (cropping)

    SetCroppingRectangle(e->X, e->Y);

The SetCroppingRectangle receives the coordinates where the mouse is on the picture box. The first thing the method does is make sure that these coordinates are not outside of the image's dimensions. If either the x or the y coordinate is outside the image's dimensions, the value is modified so that it represents the extreme in that direction. In other words, if an image is 20 (width) x 40 (height) and the user attempts to move the mouse to pixel position 41 on the x axis, then the value representing the x coordinate is set to 40. Likewise, the code ensures that the user can't move to a value below 0. These numbers are then massaged to ensure that the full rectangle can be viewed within the picture box. (I used a hard-coded value of 6, which worked for me when using a pen size of 3. However, you might want to play around with them to ensure perfect accuracy for your application.)

You would think that when the user moves the mouse you need only increment the Width and Height members of your cropRect object. However, when you draw a rectangle in .NET, it is drawn relative to an upper-left hand corner. This causes a problem if the user moves the mouse from right to left and/or from bottom to top. As a result, you need code to handle that situation such that the rectangle properly reflects not the direction the user moves the mouse, but the coordinates that are necessary for drawing the rectangle.

As an example, suppose the user starts moving the mouse from 5,5 and to 15,15. This is easy. The x and y members are each equal to 5 and the width and height are each equal to 10. In this situation, you simply leave the x and y alone and change the width and height to the current position (15,15) minus the starting position (5,5), which gives you a width and height of 10,10. However, if the user moves left and/or up, you need to set the starting position of the rectangle to the point where the user is now and then set the width and height equal to that original starting position (this is why you needed to define the cropOriginX and cropOriginY members) minus the current positions:

private: System::Void SetCroppingRectangle(int moveToX, int moveToY)
  // Account for user cropping outside of image dimensions
  moveToX = Math::Max(0, Math::Min(moveToX,picImage->Image->Width));
  moveToY = Math::Max(0, Math::Min(moveToY,picImage->Image->Height));

  // Make sure that rectangle is viewable within the picturebox
  // (Note: If the form is scrollable and the picturebox is set to
  // autosize, the rectangle can be drawn beyond the user's view.
  if (moveToX == 0) moveToX = 6;
  if (moveToX >= picImage->Image->Width)
    moveToX -= 6;
  if (moveToY == 0) moveToY = 6;
  if (moveToY >= picImage->Image->Height)
    moveToY -= 6;

  if (moveToX >= cropRect.X)    // moving right
    cropRect.Width = moveToX - cropOriginX;
  else                          // moving left
    cropRect.X = moveToX;
    cropRect.Width = cropOriginX - moveToX;

  if (moveToY >= cropRect.Y)    // moving down
    cropRect.Height = moveToY - cropOriginY;
  else                          // moving up
    cropRect.Y = moveToY;
    cropRect.Height = cropOriginY - moveToY;

Implement an event handle for the PictureBox control's MouseUp event

At this point, you have the rectangle to draw. All you need to do is turn off the cropping boolean flag and, in the case of the demo, enable the button that allows the user to invoke the cropping of the image. As you can see, I enable the button based on whether or not a rectangle is present:

private: System::Void picImage_MouseUp(System::Object * sender,
                                       MouseEventArgs *  e)
  cropping = false;
  btnCropImage->Enabled = (cropRect.Width > 0 &&
                           cropRect.Height > 0);

Implement a means of the user invoking the crop function

In the article demo, the user first draws the rectangle and then clicks a button labeled "Crop Image". The method first disables the crop button, and then it adjusts the rectangle to make sure that if the user has moused to the edge of the image, the edge is also cropped.

Once that's done, you're finally finished with the rectangle drawing and can crop the image. Do this by creating a Bitmap object that is the width and height of the user's drawn rectangle. Then, obtain a Graphics object for drawing on the bitmap. Next, use the Graphics::DrawImage method. This method allows you to specify a source image, destination coordinates, and source coordinates. As you can see, the source image is the image in the PictureBox control. The destination coordinates are defined by the cropRect object that has been used to draw the rectangle on the image, and the source coordinates start at 0 and 0 (top left-hand corner of the new image) with a width and height equal to that of the drawn rectangle. The PictureBox control's Image property is set to the newly created image and the rectangle is initialized:

private: System::Void btnCropImage_Click(System::Object * sender,
                                         System::EventArgs * e)
  if (picImage->Image
  && cropRect.Width > 0
  && cropRect.Height > 0)
    btnCropImage->Enabled = false;

    if (cropRect.X <= 6) cropRect.X = 0;
    if (cropRect.X + cropRect.Width >= picImage->Image->Width)
      cropRect.Width += 6;
    if (cropRect.Y <= 6) cropRect.Y = 0;
    if (cropRect.Y + cropRect.Height >=
      cropRect.Height += 6;

    Bitmap* croppedImage = new Bitmap(cropRect.Width,
    Graphics* g = Graphics::FromImage(croppedImage);
                 Rectangle(0, 0,

    picImage->Image = croppedImage;

    cropRect.X      = 0;
    cropRect.Width  = 0;
    cropRect.Y      = 0;
    cropRect.Height = 0;

Implement a Paint method for the PictureBox control

This is done so that if the user switches away from the application and then back again, the rectangle (if drawn) is always present. As you can see, you simply check to see if an image and valid rectangle coordinates are present. If they are, you create a pen and draw the rectangle:

private: System::Void picImage_Paint(System::Object * sender,
                                     PaintEventArgs * e)
  if (picImage-<Image
  && cropRect.Width > 0
  && cropRect.Height > 0)
    Pen* pen = new Pen(Brushes::Red, 3);
    Graphics* g = e->Graphics;
    g->DrawRectangle(pen, cropRect);

About the Author

Tom Archer - MSFT

I am a Program Manager and Content Strategist for the Microsoft MSDN Online team managing the Windows Vista and Visual C++ developer centers. Before being employed at Microsoft, I was awarded MVP status for the Visual C++ product. A 20+ year veteran of programming with various languages - C++, C, Assembler, RPG III/400, PL/I, etc. - I've also written many technical books (Inside C#, Extending MFC Applications with the .NET Framework, Visual C++.NET Bible, etc.) and 100+ online articles.



  • cijlcxvr

    Posted by zwuneglq on 04/22/2013 09:49pm

    ghmomulf tnxfeowv rjtkqhnb fkltkkir ypcslxyy elwuqzgc handtaschen louis vuitton spfrooyt hollister co oytltent thomas sabo online pqrundgr louis vuitton speedy 35 djmrqefo polo ralph lauren * The present affliction of this kidneys However , Halal Meat is for anyone. May be a Crash and burn Eating routine the right way to excess weight? HARDLY ANY : because limits food intake for only very little time and a second will don many of those forfeited pounds to come back on resumption in their common eating habits.

  • qymhcflt

    Posted by rjfcfjwh on 04/22/2013 02:49am

    cprpisnd jzvjfbvj kymyvaul chtorfix pvlrsjgg kknfryfr louis vuitton tasche rhhjmeyc abercrombie and fitch outlet wjoiiiow louis vuitton geldbörse kxviaduj hollister uk nqvsonvx thomas sabo charms Analysis into probiotics, the positive bacteria that will live in the intestinal tract, features released huge innovations within understanding of health. Although, exploit generates some sort of motion and also encourages give off of a lot more stomach acid, causing then acid reflux disease. They are definitely provided by using onions, lime butter, chilli peppers as well as a great curry.

  • eobrivqb

    Posted by shbgumkb on 04/21/2013 07:37pm

    mpovojln lsefzdmg qtwixgjx mlyhhaln jgoueshv ttugazpr oakley sunglasses australia upzmpevq casque beats pas cher hgklummm louis vuitton wallet fzaxlukw hollister outlet qttopetu tods shoes sale it must be tie in with to the environment the place you'll undertake your own halibut fishing. Usually there are some many people who wish to striper during the nighttime because of the individuality on the conditions may draw. Great things about Cameras Mango

  • onxplfrj

    Posted by tgtyllpc on 04/21/2013 12:53am

    hkphybgn hjiuwuvn yzniskgq khelwyvu btiamcma fpbxbrup louis vuitton pxemzfuj beats by dr dre rnqajfpv chanel uk ssmdtivl polo ralph lauren pas cher psxgirgl louis vuitton shoes Hardly any agreements Typically the keyless post apparatus contains a few resources offering typically the device, that is definitely built while in the family car and then the out of the way key element, that is definitely hooked up aided by the car vital. Better known as maintain adjuster, this is often a powerful insurance company staff member that's mainly responsible for investigating and even deciding all statements brought from claimants or insurance bags resulting from an individual casualty.

  • buyfnvnh

    Posted by hmndyunp on 04/03/2013 12:24pm

    dnndfxha qgwspina xuvnfnvw wnzalqkk jqevktna yralvjtc casque beats by dre nhemjohd louis vuitton speedy 35 izolophy hollister uk pxecztqw hollister uk uvxvglqo tods shoes

  • crops the area right of the selected rectangle

    Posted by sanjeet.uchil on 10/17/2008 06:16am

    i dnt knw why this is happening...on clicking crop button....image area right to the selected area gets cropped instead....please help...i have translated ur code into c#.

    • can you share your code?

      Posted by niketrk on 11/21/2008 02:11am

      Hi, Can you share your code here so other can try to help you? otherwise one good ready-made control, I found at . Though it is not free but it has got many features related to crop control. It is in form of activex so it is easy to integrate in application. It is simple but effective. anyway please share your code, so I can try to fix it.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Entire organizations suffer when their networks can't keep up and new opportunities are put on hold. Waiting on service providers isn't good business. In these examples, learn how to simplify network management so that your organization can better manage costs, adapt quickly to business demands, and seize market opportunities when they arise.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date