Introduction
This control extends the capability of an ImageBox
by including scrollbars to pan the image and a method for zooming the size of the image. My goal here is to show you two things:
- How to create your own controls that extend the
System.Windows.Forms
controls.
- How to add zoom/pan capability to an image display in a simple fashion.
Creating the control
Using Microsoft Visual Studio .NET, the easiest way to create a control is to begin by right-clicking on the project and selecting "Add -> Add User Control".
The Zoom
control was created by adding a GroupBox
, TrackBar
, and three Label
s for the minimum zoom (25%), center zoom (100%) and maximum zoom (300%). I set the Anchor
property of the GroupBox
and TrackBar
to "Right, Top, Left" so that resizing the window will resize the width of these controls. To keep the 100% Label
aligned to the center of the GroupBox
, I set the Anchor
property to "Top
".
The Image
control with automatic scroll bars was created by dropping a Panel
onto the control and sizing it to fill the remaining section of the control (below the Zoom
control) and setting its Anchor
property to "Left, Top, Right, Bottom" so that it will resize with the control. Set the AutoScroll
property to "true
". Finally, I dropped an ImageBox
inside the panel with Location = 0,0
and SizeMode=StretchImage
.
The properties must be set with AutoScroll=true
and SizeMode=StretchImage
in order for the zoom and scroll bars to work properly.
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.TrackBar scrollZoom;
private System.Windows.Forms.Label lblMax;
private System.Windows.Forms.Label lblMin;
private System.Windows.Forms.Label lblCenter;
private System.Windows.Forms.Panel imagePanel;
private System.Windows.Forms.PictureBox imgBox;
Developing the code
At this point it becomes very simple. By placing the ImageBox
inside a Panel
with AutoScroll=true
, the Panel
will automatically add scrollbars when the ImageBox
size exceeds the size of the Panel
. So, all you have to do is to add code to get or set the image and a little bit of code to control the zoom.
The image is set by adding a public
property. In this case, I chose to make the property available at design time by setting Browsable(true)
. I also re-center the zoom scroll when a new image is loaded and disable the zoom scroll if the image is null
. Finally, I set the size of the ImageBox
equal to the size of the Image
for a zoom factor of 100%.
As mentioned in the comments below by yfoulon, adding scrollZoom.Focus()
should allow the use of mousewheel to zoom the image. (I don't have a mouse so I was unable to test this.)
true),
Description("Image loaded into the box.")>
public Image Image
{
get
{
return imgBox.Image;
}
set
{
imgBox.Image = value;
scrollZoom.Enabled = (value != null);
if (scrollZoom.Enabled)
{
scrollZoom.Value = this.scrollZoom.Maximum/2;
imgBox.Size = value.Size;
}
else
{
imgBox.Size = imagePanel.Size;
}
}
}
The zoom is handled with an EventHandler
that calls a method when the user scrolls the zoom TrackBar
. The zoom factor is currently a hard-coded array with 11 elements which is the same as the number of positions on the TrackBar
(min = 0, center = 5, max = 10). The ImageBox
is then resized by multiplying the Image
size by the new zoom factor. Because the ImageBox
's SizeMode
is set to "StretchImage
", the Image
will be scaled to fit the new size of the ImageBox
.
private double[] zoomFactor =
{.25, .33, .50, .66, .80, 1, 1.25, 1.5, 2.0, 2.5, 3.0};
private void scrollZoom_Scroll(object sender,
System.EventArgs e)
{
setZoom();
}
private void setZoom()
{
double newZoom = zoomFactor[scrollZoom.Value];
imgBox.Width =
Convert.ToInt32 ( imgBox.Image.Width * newZoom);
imgBox.Height =
Convert.ToInt32 ( imgBox.Image.Height * newZoom );
}
Additionally, I also added a KeyDown
event handler and some code to allow the user to increase or decrease the zoom factor using the Ctrl+ and Ctrl- keys.
private void ImageBoxPanZoom_KeyDown(object sender, KeyEventArgs e)
{
if (scrollZoom.Enabled)
{
if((e.KeyData == (Keys.Oemplus | Keys.Control)) &&
(scrollZoom.Value != scrollZoom.Maximum))
{
scrollZoom.Value++;
setZoom();
}
else if ((e.KeyData == (Keys.OemMinus | Keys.Control)) &&
(scrollZoom.Value != scrollZoom.Minimum))
{
scrollZoom.Value--;
setZoom();
}
}
}
Points of interest
At some point, I would like to revisit this project and add a method of scrolling the image by using the arrow keys and/or the mouse.
History
- 12/01/05 - Thanks to yfoulon for correcting a mistake I made in the original article. It's even simpler than I thought! :)