Creating a scrollable and zoomable image viewer in C# Part 2
In the second part of our Creating a scrollable and zoomable image viewer in C# series we will update our component to support automatic scrolling when auto size is disabled and the image is larger than the client area of the control.
Setting up auto scrolling
Originally we inherited from Control
, however this does not
support automatic scrolling. Rather than reinventing the wheel
at this point, we'll change the control to inherit from
ScrollableControl
instead. This will expose a number of new
members, the ones we need are:
AutoScroll
- Enables or disables automatic scrollingAutoScrollMinSize
- Specifies the minimum size before scrollbars appearAutoScrollPosition
- Specifies the current scroll positionOnScroll
- Raised when the scroll position is changed
Using the above we can now offer full scrolling.
As the control will take care of the scrolling behaviour, we
don't want the AutoScrollMinSize
property to be available, so
we'll declare a new version of it and hide it with attributes.
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new Size AutoScrollMainSize
{
get { return base.AutoScrollMinSize; }
set { base.AutoScrollMinSize = value; }
}
Initially the component only offered auto sizing and so we had
defined an AdjustSize
method which was called in response to
various events and property changes. As we now need to set up
the scrolling area if AutoScroll
is enabled, this method is no
longer as suitable. Instead, we add a pair of new methods,
AdjustLayout
and AdjustScrolling
. Existing calls to
AdjustSize
are changed to call AdjustLayout
instead, and
this method now calls either AdjustScrolling
or AdjustSize
depending on the state of the AutoSize
and AutoScroll
properties.
The AdjustScrolling
method is used to set the
AutoScrollMainSize
property. When this is correctly set, the
ScrollableControl
will automatically take care of displaying
scrollbars.
protected virtual void AdjustLayout()
{
if (this.AutoSize)
this.AdjustSize();
else if (this.AutoScroll)
this.AdjustScrolling();
}
protected virtual void AdjustScrolling()
{
if (this.AutoScroll && this.Image != null)
this.AutoScrollMinSize = this.Image.Size;
}
Reacting to scroll changes
By overriding the OnScroll
event we get notifications whenever
the user scrolls the control, and can therefore redraw the
image.
protected override void OnScroll(ScrollEventArgs se)
{
this.Invalidate();
base.OnScroll(se);
}
Painting adjustments
The initial version of our ImageBox
tiled a bitmap across the
client area of the control. In this new version, when we create
the background tile, we now create a new TextureBrush
. During
drawing we can call FillRectangle
and pass in the new brush
and it will be tiled for us.
Another shortcoming of the first version was the borders. These were painted last, so that if the image was larger than the controls client area, the image wouldn't be painted on top of the borders. Now, the borders are drawn first and a clip region applied to prevent any overlap.
Finally of course, the position of the drawn image needs to reflect any scrollbar offset.
protected override void OnPaint(PaintEventArgs e)
{
int borderOffset;
Rectangle innerRectangle;
borderOffset = this.GetBorderOffset();
if (borderOffset != 0)
{
// draw the borders
switch (this.BorderStyle)
{
case BorderStyle.FixedSingle:
ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle, this.ForeColor, ButtonBorderStyle.Solid);
break;
case BorderStyle.Fixed3D:
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, Border3DStyle.Sunken);
break;
}
// clip the background so we don't overwrite the border
innerRectangle = Rectangle.Inflate(this.ClientRectangle, -borderOffset, -borderOffset);
e.Graphics.SetClip(innerRectangle);
}
else
innerRectangle = this.ClientRectangle;
// draw the background
if (_texture != null && this.ShowGrid)
e.Graphics.FillRectangle(_texture, innerRectangle);
else
{
using (SolidBrush brush = new SolidBrush(this.BackColor))
e.Graphics.FillRectangle(brush, innerRectangle);
}
// draw the image
if (this.Image != null)
{
int left;
int top;
left = this.Padding.Left + borderOffset;
top = this.Padding.Top + borderOffset;
if (this.AutoScroll)
{
left += this.AutoScrollPosition.X;
top += this.AutoScrollPosition.Y;
}
e.Graphics.DrawImageUnscaled(this.Image, new Point(left, top));
}
// reset the clipping
if (borderOffset != 0)
e.Graphics.ResetClip();
}
Sample Project
You can download the second sample project from the link below. The next article in the series will look at panning the image using the mouse within the client area of the image control.
Update History
- 2010-08-13 - First published
- 2020-11-21 - Updated formatting
Related articles you may be interested in
- Displaying multi-page tiff files using the ImageBox control and C#
- Adding drag handles to an ImageBox to allow resizing of selection regions
- ImageBox 1.1.4.0 update
- ImageBox and TabList update's - virtual mode, pixel grid, bug fixes and more!
- ImageBox update, version 1.1.0.0
- Zooming to fit a region in a ScrollableControl
- Zooming into a fixed point on a ScrollableControl
- Arcade explosion generator
- Creating an image viewer in C# Part 5: Selecting part of an image
- Extending the ImageBox component to display the contents of a PDF file using C#
- Creating a scrollable and zoomable image viewer in C# Part 4
- Creating a scrollable and zoomable image viewer in C# Part 3
- Creating a scrollable and zoomable image viewer in C# Part 1
Downloads
Filename | Description | Version | Release Date | |
---|---|---|---|---|
imageboxsample-part2.zip
|
Second in a multi part series on creating an image viewer that can be scrolled and zoomed in C#. After part one created the initial component with auto resize, we now add scrolling support. |
13/08/2010 | Download |
Leave a Comment
While we appreciate comments from our users, please follow our posting guidelines. Have you tried the Cyotek Forums for support from Cyotek and the community?
Comments
Jason
#
I am looking for some good sample for showing image. I want to try your sample.