Click here to Skip to main content
13,259,194 members (51,795 online)
Click here to Skip to main content
Add your own
alternative version


108 bookmarked
Posted 7 Mar 2006

Click to Drag, Zoom, and Copy - PictureBox

, 23 Jan 2007
Rate this:
Please Sign up or sign in to vote.
A picture box with built-in click to drag, zoom, and copy.

Click and Drag to Zoom


This control was originally developed to mimic some existing software that my company was using to view and process medical claims. The original plan was to develop a PictureBox that would allow the users to draw a box on the image and then zoom in on that point. It was immediately apparent that this would be no easy task.


The PictureBoxEx still uses .NET 1.1 to make it more compatible with current and future projects, but has been completely rewritten.

This control is a completely new control, it is no longer based on a PictureBox but a ScrollableControl. Making this switch was necessary to create a control that was both flexible and fast. When drawing the drag window, the old control was slow to build the image and refresh, whereas the new control is very smooth.

This new version also contains the ability to add annotations to the images. These annotations can be colored, resized to match the image's current zoom, and best of all are XmlSerializable, so they can be saved to file and retrieved later.

Scrolling was also added to this new control. The control now has the ability to be scrolled vertically and horizontally, by both the keys and the mouse. Scrolling the wheel causes the image to be scrolled vertically, but if you hold the control key while scrolling the mouse wheel, the image can now be scrolled horizontally. The arrow keys plus Home, End, PageUp, PageDown can all be used to scroll the image. Because the control is unable to receive and hold direct focus, the focus can shift from control to control on the same form. So to make use of the key scrolling, it is best to make this PictureBoxEx the only control on the form. (If anyone knows how to improve this limitation, I would love to hear about it.)

Also the current zoom of the control can be changed by scrolling the mouse wheel while holding the shift key down.


  1. Click and drag window to zoom or copy
  2. Parentless design (New)
  3. Annotate (Includes custom cursor) (New)
  4. Diagnostics mode (New)
  5. Zoom and scroll with the mouse wheel (New)
  6. Scroll with keys (Works best if the only control on form) (New)

Custom Properties

Most of the controls custom properties are available through the designer.

  • AllowDrag: Indicates whether or not the user should be allowed to drag and copy or zoom
  • CurrentZoom: Controls the PictureBox's current zoom.
  • DefaultZoom: Controls the PictureBox's default zoom.
  • DiagnosticMode: Set to true to display diagnostics information.
  • DoubleClickRestore: Controls the PictureBox's ability to restore the image to the default zoom on double-click.
  • DragOptions: Controls the PictureBox's drag options. (Copy, Zoom, or Prompt)
  • DragWindowColor: Controls the PictureBox's drag window color.
  • DragWindowMinimum: Controls the PictureBox's minimum invokable drag window size.
  • DragWindowPattern: The dash pattern that is used by the control when drawing the drag window.
  • DrawMode: Controls the imaging filter that will be applied to the image if it is resized. (InterpolationMode)
  • MaximumZoom: Controls the maximum allowed zoom.
  • MinimumZoom: Controls the minimum allowed zoom.

The Code

The following code is used by GenerateResizedImage to generate the resized image from the backup which is created when the Image property of the control is set. The creating of the resized image happens regardless of the current zoom, even if it's 1. The reason it's generated anyway is because the control can't work with images of an indexed pixel format. So it's just easier to convert the images straight away.

int resizedWidth  = Convert.ToInt32(backup.Width  * _currentZoom);
int resizedHeight = Convert.ToInt32(backup.Height * _currentZoom);
resized = new Bitmap(resizedWidth, resizedHeight);

// Drag the backup image onto the resized image
using (Graphics g = Graphics.FromImage(resized))
    g.InterpolationMode = (_currentZoom < 1F) ? 
               _drawMode : InterpolationMode.Default;

    Rectangle srceRect = 
       new Rectangle(0, 0, backup.Width, backup.Height);
    Rectangle destRect = 
       new Rectangle(0, 0, resized.Width, resized.Height);

    g.DrawImage(backup, destRect, srceRect, GraphicsUnit.Pixel);

    // Add any annotations to the resized image

Determining where the zoom should occur requires a lot of math. The first step it to compensate for the current zoom and the current scroll position. Then, it needs to be determined which part of the drag window is larger in proportion to the size of the control, and enlarge that section to fill the control while centering the remainder.

// The zoom window will never be proportional to the container, so one
//  side will get filled while the other gets centered. The larger % will
//  determine which gets filled, and which gets centered
float xRatio = (float)Width / (float)dragWindowSave.Width;
float yRatio = (float)Height / (float)dragWindowSave.Height;

float largerRatio;
int xAdjust = 0;
int yAdjust = 0;

largerRatio = (xRatio < yRatio) ? xRatio : yRatio;

// The cumulative zoom cannot exceed the maximum zoom;
if ((largerRatio * _currentZoom) > _maximumZoom)
    largerRatio = _maximumZoom / _currentZoom;

if (dragWindowSave.Width * largerRatio > Width)
    largerRatio = (float)Width / (float)dragWindowSave.Width;

if (dragWindowSave.Height * largerRatio > Height)
    largerRatio = (float)Height / (float)dragWindowSave.Height;

yAdjust = Convert.ToInt32(
    ((float)Height - (float)dragWindowSave.Height * largerRatio) / 2F);
xAdjust = Convert.ToInt32(
    ((float)Width - (float)dragWindowSave.Width * largerRatio) / 2F);

int xScrollPos = Math.Max(Convert.ToInt32(((float)-AutoScrollPosition.X + 
                         (float)dragWindowSave.X) * largerRatio) - xAdjust, 0);
int yScrollPos = Math.Max(Convert.ToInt32(((float)-AutoScrollPosition.Y + 
                         (float)dragWindowSave.Y) * largerRatio) - yAdjust, 0);
CurrentZoom *= largerRatio;

Using the Control

The control is very much like a PictureBox. All that really needs to be done is to add the control to a form and set its Image property.

  1. Add a reference to the Build DLL.
  2. Add the control to your form.
  3. Set the desired control properties.
  4. Set the control's Image property.

Lessons Learned

This control has an event that fires after the image has been changed. If subscribers of this event take a lot of time or processor power, it will appear to have a negative impact on the performance of this control.

Without a backup image, the zooming process (in and out) will degrade image quality.

Known Issues

  1. Some designer mode instability.
  2. Some issues with the border styles not being drawn correctly.


This control was developed for Trusted Plans Service Corp. Tacoma WA.

  • Version 1 - released 3/6/2006.
  • Version 2 - released 12/12/2006.


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

United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralGreat Work Pin
Mohsen Malekan19-Mar-13 12:20
memberMohsen Malekan19-Mar-13 12:20 
GeneralMy vote of 5 Pin
manoj kumar choubey28-Feb-12 23:42
membermanoj kumar choubey28-Feb-12 23:42 
GeneralMy vote of 5 Pin
suhaslive13-Jan-11 22:25
membersuhaslive13-Jan-11 22:25 
GeneralArrow keys change control in focus Pin
Diamonddrake27-Nov-09 17:43
memberDiamonddrake27-Nov-09 17:43 
GeneralZoom Not Working Correctly when not prompting Pin
romercha30-Sep-07 4:50
memberromercha30-Sep-07 4:50 
GeneralRelase image after use Pin
eblaschka19-Feb-07 15:37
membereblaschka19-Feb-07 15:37 
GeneralDoubleClickRestore Pin
BillAPgh2-Feb-07 8:38
memberBillAPgh2-Feb-07 8:38 
GeneralGood work + question.. Pin
zoodany12-Dec-06 2:01
memberzoodany12-Dec-06 2:01 
Congratulation for your work..
For my project I need to add dinamically (they could change every time) some MenuItems to the context menu that appear when I drag on the PictureBoxEx (the one with "Copy" and "Zoom") and to associate them with some functions.. How can I do this?

Thank you very much...


PS: sorry for my english, I'm italian and I don't speak english very well...
GeneralRe: Good work + question.. Pin
gbarcalow12-Dec-06 20:43
membergbarcalow12-Dec-06 20:43 
GeneralLicense Pin
Athmok21-Sep-06 4:39
memberAthmok21-Sep-06 4:39 
GeneralGood work Pin
Sander van Driel14-Mar-06 1:21
memberSander van Driel14-Mar-06 1:21 
GeneralRe: Good work Pin
gbarcalow14-Mar-06 17:22
membergbarcalow14-Mar-06 17:22 
Generalpopup menu doesn't always popup when dragging mouse Pin
Sir Tigercool8-Mar-06 5:51
memberSir Tigercool8-Mar-06 5:51 
GeneralRe: popup menu doesn't always popup when dragging mouse Pin
gbarcalow14-Mar-06 17:25
membergbarcalow14-Mar-06 17:25 
GeneralTpsc.PictureBoxEx.dll Pin
saegezauberer7-Mar-06 22:28
membersaegezauberer7-Mar-06 22:28 
GeneralRe: Tpsc.PictureBoxEx.dll Pin
Sander van Driel14-Mar-06 1:09
memberSander van Driel14-Mar-06 1:09 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171114.1 | Last Updated 23 Jan 2007
Article Copyright 2006 by gbarcalow
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid