Click here to Skip to main content
Click here to Skip to main content
Go to top

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

Introduction

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.

Changes

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.

Features

  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
    DrawAnnotations(g);
}

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.

History

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

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

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

Share

About the Author

gbarcalow

United States United States
No Biography provided

Comments and Discussions

 
GeneralGreat Work PinmemberMohsen Malekan19-Mar-13 11:20 
GeneralMy vote of 5 Pinmembermanoj kumar choubey28-Feb-12 22:42 
GeneralMy vote of 5 Pinmembersuhaslive13-Jan-11 21:25 
good work
GeneralArrow keys change control in focus PinmemberDiamonddrake27-Nov-09 16:43 
GeneralZoom Not Working Correctly when not prompting Pinmemberromercha30-Sep-07 3:50 
GeneralRelase image after use Pinmembereblaschka19-Feb-07 14:37 
GeneralDoubleClickRestore PinmemberBillAPgh2-Feb-07 7:38 
GeneralGood work + question.. Pinmemberzoodany12-Dec-06 1:01 
GeneralRe: Good work + question.. Pinmembergbarcalow12-Dec-06 19:43 
GeneralLicense PinmemberAthmok21-Sep-06 3:39 
GeneralGood work PinmemberSander van Driel14-Mar-06 0:21 
GeneralRe: Good work Pinmembergbarcalow14-Mar-06 16:22 
Generalpopup menu doesn't always popup when dragging mouse PinmemberSir Tigercool8-Mar-06 4:51 
GeneralRe: popup menu doesn't always popup when dragging mouse Pinmembergbarcalow14-Mar-06 16:25 
GeneralTpsc.PictureBoxEx.dll Pinmembersaegezauberer7-Mar-06 21:28 
GeneralRe: Tpsc.PictureBoxEx.dll PinmemberSander van Driel14-Mar-06 0:09 

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 | Mobile
Web03 | 2.8.140926.1 | Last Updated 23 Jan 2007
Article Copyright 2006 by gbarcalow
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid