Click here to Skip to main content
Click here to Skip to main content

A Zoomable and Scrollable PictureBox

By , 31 May 2008
 

Introduction

A big question in the Windows Forms world is "How can I zoom and scroll the PictureBox?" The answer is to use the ImagePanel, which enables you to simply zoom and pan an image.

I use Microsoft Visual C# 2005 Express Edition to build it. It's easy and simple. You can start a new project and add a user control. In the Design window, you drag a vertical scrollbar and a horizontal scrollbar to the user control, then go to the code window and add the code as in the source file, ImagePanel.cs. That's all, a zoomable and scrollable PictureBox replacement has been built and you can use it now.

Zooming is done by a Matrix object:

Matrix mx=new Matrix(); // create an identity matrix
mx.Scale(zoom,zoom); // zoom image

Panning is done by the values returned by the scrollbars. We tell the scrollbar the image size, which is its real size multiplied by the zoom factor:

if ((canvasSize.Width * zoom - viewRectWidth) > 0)
{
    this.hScrollBar1.Maximum =(int)( canvasSize.Width * zoom) - viewRectWidth;
}
if ((canvasSize.Height * zoom - viewRectHeight) > 0)
{
    this.vScrollBar1.Maximum = (int)(canvasSize.Height * zoom) - viewRectHeight;
}

So, the correct position within the real image is the scrollbar values divided by the zoom factor:

Point pt=new Point((int)(hScrollBar1.Value/zoom),(int)(vScrollBar1.Value/zoom));

To display the image on the center of this control, the Matrix object is used again:

mx.Translate(viewRectWidth/2.0f,viewRectHeight/2.0f, MatrixOrder.Append);

This component has a good feature: during image zoom out, only a portion of the image is drawn. It saves a lot of computer resources:

if (canvasSize.Width * zoom < viewRectWidth && 
            canvasSize.Height * zoom < viewRectHeight)
    srcRect = new Rectangle(0, 0, canvasSize.Width, canvasSize.Height);
    // view all image
else srcRect = new Rectangle(pt, new Size((int)(viewRectWidth / zoom), 
                            (int)(viewRectHeight / zoom)));
// view a portion of image

To test this little but strong control, I put it on a form and added a trackbar to provide the zoom factor. Double click the ImagePanel to load a picture. Try it, how's it?

Thanks.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

YLS CS
Unknown
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionhow can i add dragging options?memberMember 838204526 Dec '12 - 1:09 
Hey,
I'm just curious - is it possible to add some options for dragging (and moving) the image? I want to make a google maps-like control out of this and dragging is the last thing remaining.
 
Could you please give me the general guidelines (names of key functions to use) as to how to do it?
I can capture mouse movement, I just can't effectively "draw" the part of the picture moved by a few pixels whenever a mouse moved...
 
Thank you!
GeneralMy vote of 5membermanoj kumar choubey1 Mar '12 - 22:53 
nice
GeneralExactly what I was looking formemberEpikYummeh29 Nov '11 - 15:36 
I have been trying to find a solution for the PictureBox control restrictions, and this is just what I needed. Thanks so much.
Generalthanksmemberasugix18 Jul '10 - 4:01 
Thank's for this tutorial. I need many example to create my software
No one can prevent me to learn something

GeneralGreat work!membersintesia25 Mar '10 - 6:56 
You did a great work indeed.
This is just what I needed.
Bye!
Give me something to code for, and I'll be by your side until the end - Maurizio Dagradi

GeneralA Little Memory Used More Than RequaredmemberMember 278444925 Mar '09 - 17:21 
In the paint function this might help:
 
if (g != null)
{
g.Dispose();
}
g=e.Graphics;
 
insted of:
Graphics g=e.Graphics;
QuestionHow can i transfer this to Windows Mobile 6?memberwomisa1 Mar '09 - 11:45 
Hi

Thanks for your article.
How can i do ths funcionality in Windows Mobile 6 with the CompactFramework 2.0?
 
Thank for each answer
Achim
Questionimage is not kept centered when zoommemberdvisions20 Sep '08 - 4:17 
is the image suppose to shifts towards the topleft whenever you zoom?
 
if so, how do i make it zoom towards the center of the current view?

i think my problem is this line in the onPaint method:
 
Point pt = new Point((int)(hScrollBar1.Value / zoom), (int)(vScrollBar1.Value / zoom));
 
can someone help?.
AnswerRe: image is not kept centered when zoommemberrichardn6617 Feb '10 - 9:28 
let me know if u still need help with this as I've just come across this project and tailored it to my requirements with the following
- center zooming
- image doesn't just to left when horizontal scroll is not visible but vertical is (and vice versa)
- panning (through the adaption of someone else's panning code)
 
Richard
Visionscape
GeneralRe: image is not kept centered when zoommemberflacolarry19 Feb '10 - 13:41 
Can you share how you do you keep the image centered when zooming?
 
Thanks.
QuestionHow about to add croping, resizing?memberDemaker2 Jul '08 - 1:20 
It will be a good control!
Generalmaybe simplified versionmemberHuanacaraz2 Jun '08 - 21:38 
UserControl has scrolling build in, so you dont need to use another scrollbars. Just set control's AutoScroll property to true and set the AutoScrollMinSize property to the desired size. AutoScrollPosition then contains coordinate of control's origin (0,0).
 
Sample:
OnPaint() ....
      //------------- first calculate coordinates of internal 0,0 (centering)
      Point origin = new Point(0 + AutoScrollPosition.X, 0 + AutoScrollPosition.Y);
      if (this.ClientSize.Width > this.container.Bounds.Width)
        origin.X = (this.ClientSize.Width - this.container.Bounds.Width) / 2;
      if (this.ClientSize.Height > this.container.Bounds.Height)
        origin.Y = (this.ClientSize.Height - this.container.Bounds.Height) / 2;
 
      //-- set move and scale transformations to graphics
      //   so we can use normal coordinates when painting graphic objects
      Graphics g = e.Graphics;
      g.TranslateTransform(origin.X, origin.Y);
      if (scaleMode) g.ScaleTransform(scaleValue[0], scaleValue[1]);
 
      //Paint control backgound
      g.FillRectangle(bgBrush, g.VisibleClipBounds);
 
      //user paint 

AnswerRe: maybe simplified versionmemberYLS CS3 Jun '08 - 4:33 
Thank you very much for your suggestion.
 
I tried AutoScroll before. I wanted to put the image on the container center when image zoomed in. But I really didn't know how the image location change while zooming. I wonder only setting the AutoScrollMinSize is not enough. I will try again. Thanks.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 31 May 2008
Article Copyright 2008 by YLS CS
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid