ImageBox update, version

The ImageBox control has had quite a big update, you can download the source from the link below, or from our GitHub page.

Listed below are the changes made during this update, we hope you enjoy them!

The updated ImageBox demonstration application
The updated ImageBox demonstration application

Changes and new features

  • Zooming with the mouse is now smoother, and the control attempts to keep the area under the mouse before the zoom in the same area after the zoon.
  • Added a ZoomLevels property which allows you to configure the different zoom levels supported by the control. Now instead of the control trying to guess the next zoom level, it cycles appropriately through the defined levels. Currently ZoomLevels (apart from the default series) can only be set at runtime.
  • The ZoomIncrement property has been removed due to the introduction of the new zoom levels.
  • New CenterAt and ScrollTo methods allow you to scroll to a given location in the source image.
  • Split shortcut handling into two methods ProcessScrollingShortcuts for handling arrow keys and ProcessImageShortcuts for handling pretty much anything else.
  • Added EnableShortcuts property, allowing the built in keyboard support to be disabled. When this property is true, ProcessImageShortcuts is not called, allowing the control to still be scrolled via the keyboard, but not zoomed etc.
  • Zooming can now be performed by the -/+ keys (OemMinus and Oemplus).
  • When zooming (except via mouse action), if the AutoCenter property is set, the control will always center the image even when scrollbars are present.
  • Nestable BeginUpdate and EndUpdate methods allow you to disable and enable painting of the control, for example when changing multiple properties at once.
  • Added a new GetSelectedImage method which creates a new Bitmap based on the current selection.
  • Added new FitRectangle method which takes a given rectangle and ensure it fits within the image boundaries
  • The AllowClickZoom property now defaults to false.
  • The PointToImage function no longer adds +1 to the result of the function.
  • Added a new ZoomToRegion method. This will caculate and appropriate zoom level and scrollbar positions to fit a given rectangle.
  • Added new SelectionMode.Zoom. When this mode is selected, drawing a region will automatically zoom and position the control to fit the region, after which the region is automatically cleared.

Bug fixes

  • Panning no longer tries to activate if no scrollbars are visible
  • A new base class, VirtualScrollableControl is now used instead of ScrollableControl. This removes completely the flicker issues present in previous versions of the control.
  • The BorderStyle property has been moved to the ScrollControl class, so that borders now correctly surround the control (including scrollbars) rather than just the client area.
  • If the AllowZoomClick property is true, the control no longer magically zooms after panning or selecting a region. Code previously in the OnMouseClick override is now in OnMouseUp.
  • If both AutoPan and a valid SelectionMode are set, only selections are processed, instead of the control tying to do both. As a result of this fix, setting the SelectionMode property no longer resets AutoPan
  • With the introduction of the VirtualScrollableControl, the MouseWheel event is now raised as expected.

Known issues

  • The ScrollProperties class hasn't been fully integrated with the ScrollControl, setting properties on this class won't update the owner control.

Update History

  • 2012-08-30 - First published
  • 2020-11-21 - Updated formatting

Like what you're reading? Perhaps you like to buy us a coffee?

Donate via Buy Me a Coffee

Donate via PayPal



We'll never share your email with anyone else Styling with Markdown is supported
# TeYoU

Nice project!

However, I have a question about the zoomIn & zoomOut method. Everytime I call those methods, it always start from the left upper point instead of zooming from the current viewport. Is there any solution to this?

Cheers, Teyou

# Richard Moss

Shouldn't be too hard to change the code for this, I'll look at that for the next update.


This control looks quite nice. I found a bug of the display. Please turn on the ImageBorderStyle. And set the Padding to 20 or more. Resize the window so the image is not fit in the client area. Scroll it down and right, you will see margins at the right and bottom size. BTW, the statement in ImageBox.cs: viewPort = new Rectangle(offset.X + innerRectangle.Left + this.Padding.Left, offset.Y + innerRectangle.Top + this.Padding.Top, innerRectangle.Width - (this.Padding.Horizontal + (offset.X * 2)), innerRectangle.Height - (this.Padding.Vertical + (offset.Y * 2))); can be simplified to: viewPort = new Rectangle(offset.X + innerRectangle.Left + this.Padding.Left, offset.Y + innerRectangle.Top + this.Padding.Top, this.ScaledImageWidth, this.ScaledImageHeight); which is more neat and has fixed a bug introduced by mathematical division and multiplication in the function.

# Richard Moss

Thanks for the feedback - I'll look into this and get it updated as required!

# Fajar

It is a great project. I wanna to develop this to perform map function. I have list of node position (Long,Lat) or (X,Y) relative to image. When map zoomed, that position change depend on calculation on zoom var. Something like when we put balloon position in google map and when I poiting to it, it show information of this position.Thanks

# Richard Moss


The ImageBox control has a number of GetScaled* and GetOffset* methods that can be used to convert 1:1 points and rectangles to match the current zoom level or scroll position - you should find these make it pretty simple to add those sorts of overlays to the control.

Regards; Richard Moss

# Tim Miltz

I noticed this newer version produces much grainier images when zooming in. I can not figure out what changed though. I'm using a 20 MB image that should have plenty of detail when zooming in. The earlier source shows higher quality images when zooming in. Any thoughts on what may have changed?

# Richard Moss


Thanks for your comment. I don't remember changing anything explicitly about this, the code used to the draw the image is probably unchanged since it was implemented. What is possible though is I changed the default InterpolationMode to be more appropriate (it's currently set to NearestNeigbour, which is the fastest at the expense of being blocky). You could try changing this to HighQualityBicubic and see if that helps. If this doesn't help and it's something else, perhaps drop me an email or forum post with screenshots or samples demonstrating the issue?

Regards; Richard Moss

# Jim

This is very nice but I would like to have it never show scrollbars, while maintaining the zoom/pan abilities via drag & scroll wheel. I was able to hide them but in doing so it broke the image display. What would be the correct way to accomplish that here?

# Richard Moss


I took a quick look, but all the approaches I tried did have the effect of breaking it. I didn't spend a huge amount of time looking at it, but all the approaches I tried (using ShowScrollbar, removing the WS_HSCROLL and WS_VSCROLL styles etc serve to break it. I did some other tests and the SCROLLINFO data for the control does still seem to be correct, so it's mostly likely something to do with the way the ImageBox is processing the information - in other words it should be resolvable with time.

Regards; Richard Moss

# Carlos Fernando Castaneda Olano

Thank you Mr. Richard for your blog and updates to the code (ImageBox and TabList update's - virtual mode, pixel grid and so on).

# ignacio

Richard, why don't you support CMYK?

# ignacio

Richard, why don't you support CMYK? Also in PhotoshopLoadPalettes Easy approach (approximation, without using ICC profiles) is in ReadSwatches()

  case ColorSpace.Cmyk:
        int red2;
        int green2;
        int blue2;
        //int cyan,magenta, yellow;
        int black;

        // CMYK.
        // The first three values in the color data are red , green , and blue . They are full unsigned
        //  16-bit values as in Apple's RGBColor data structure. Pure red = 65535, 0, 0.

        black = value4 /256;
        red2 = (int)(black * value1 / (256*255)); // 0-255
        green2 = (int)(black * value2 / (256*255)); // 0-255
        blue2 = (int)(black * value3 / (256*255)); // 0-255

        results.Add(Color.FromArgb(red2, green2, blue2));
# Richard Moss


Thanks for the comment, although I think you posted it to the wrong article. I did actually add CMYK support quite some time ago (March 2016 according to the commit logs!), but I haven't gotten around to republishing any source as I essentially rewrote it to avoid some of the precision issues I was finding. I have added a note to try and get around to this sooner rather than later.

Thanks again for the comment and also the sample conversion code!

Richard Moss