How to zoom in a Picturebox with scrollwheel in vb.net
Asked Answered
S

3

9

I'm using a set of graphics overlays to draw an image inside a picturebox control using the graphics object. I have placed the Picturebox inside a Panel and set the Panel to autoscroll. What I need to know how to do now is use the Mouse scroll wheel to blow up the size of the picture in small increments while maintaining the quality of the image drawn. Anyone know how to do this?

When I update with Abdias Software code below, the picture starts out smaller when Sizemode property of picturebox is set to StretchImage. I have a pan feature with the mouse that might be interfering with keeping this code from working properly. Any Ideas? What could be keeping this from working properly?

SOLVED

This code worked much better for me than any of the two below:

Private Sub PictureBox_MouseWheel(sender As System.Object,
                             e As MouseEventArgs) Handles PictureBox1.MouseWheel
    If e.Delta <> 0 Then
        If e.Delta <= 0 Then
            If PictureBox1.Width < 500 Then Exit Sub 'minimum 500?
        Else
            If PictureBox1.Width > 2000 Then Exit Sub 'maximum 2000?
        End If

        PictureBox1.Width += CInt(PictureBox1.Width * e.Delta / 1000)
        PictureBox1.Height += CInt(PictureBox1.Height * e.Delta / 1000)
    End If

End Sub
Saritasarkaria answered 21/11, 2012 at 15:39 Comment(4)
I added your code and moving was enabled as expected, and zooming works fine too. These events are anyway separate so they shouldn't interfere. The sizemode will force the image to the size of the control so if the control size is smaller than the image the image will shrink. You can in the load event (or method that sets the image) set PictureBox1.Size = New Size(bmp.Width, bmp.Height) (also update _origjnalSize with the same). Besides from that I cannot see any potential problem without seeing more of the code.Churchy
I used all your code, just different pictures obviously, but still works. (just as a side-note: I'm not sure why you put SetStyle() in there. They are meant for user controls and won't do much at this point I the code). Besides everything works as expected (even with the setstyles enabled). It's a bit of a mystery. I'm on XP btw. I don't think that matters, but it's worth to check out and hopefully eliminate if you're on other win version.Churchy
I'm using Windows 7 with Visual Studio Express 2012. Do you think it may be a bug they haven't fixed yet? I would hate to move all of this code and redraw everything to Visual Basic Express 2010. Uggg! If you don't mind me asking, what are your property settings in your PictureBox control and Panel control. Don't know if it's something simple like that. But who knows maybe I have one of mine set crazy.Saritasarkaria
Here are all my settings: pastebin.com/FnAzVKzF It could be a bug in VS2012, it certainly appears that way. Only one way to find out though.. :)Churchy
C
8

You can try this code. It assumes there exist a Panel1 and PictureBox1 on the form (PictureBox1 inside the Panel1 with Panel1.AutoScroll = True) with an image set on the PictureBox.

The code doesn't calculate center point of the zoom, but you can use the e.Location (or e.X/e.Y) for that.

Update - here is the new code that is (should be) more robust than the previous (see bottom):

Public Class Form1

    Private _originalSize As Size = Nothing
    Private _scale As Single = 1
    Private _scaleDelta As Single = 0.0005

    Private Sub Form_MouseWheel(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel

        'if very sensitive mouse, change 0.00005 to something even smaller   
        _scaleDelta = Math.Sqrt(PictureBox1.Width * PictureBox1.Height) * 0.00005

        If e.Delta < 0 Then
            _scale -= _scaleDelta
        ElseIf e.Delta > 0 Then
            _scale += _scaleDelta
        End If

        If e.Delta <> 0 Then _
        PictureBox1.Size = New Size(CInt(Math.Round(_originalSize.Width * _scale)), _
                                    CInt(Math.Round(_originalSize.Height * _scale)))

    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

        'init this from here or a method depending on your needs
        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Size = Panel1.Size
            _originalSize = Panel1.Size
        End If

    End Sub

End Class

Old code - works, but is unstable on large changes probably due to rounding errors in Scale():

Public Class Form1

    Private _scale As New SizeF(1, 1)
    Private _scaleDelta As New SizeF(0.01, 0.01) '1% for each wheel tick

    Private Sub Form_MouseWheel(sender As System.Object, 
                                e As MouseEventArgs) Handles Me.MouseWheel
'count incrementally 
        _scale.Height = 1
        _scale.Width = 1

        If e.Delta < 0 Then
            _scale += _scaleDelta
        ElseIf e.Delta > 0 Then
            _scale -= _scaleDelta
        End If

        If e.Delta <> 0 Then _
        PictureBox1.Scale(_scale)

    End Sub

    Private Sub Form1_Load(sender As System.Object, 
                           e As EventArgs) Handles MyBase.Load

        PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

        'init picturebox size = image size
        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Scale(New SizeF(1, 1))
            PictureBox1.Size = PictureBox1.Image.Size
        End If

    End Sub

End Class
Churchy answered 21/11, 2012 at 16:59 Comment(10)
I tried the code and it works good but there seems to be a major problem. When I start the program the picture box automatically shrinks the picture when it was full size to begin with before adding code. When I use the scroll wheel it makes it smaller, and when I scroll the other way it makes it bigger up until only half the picture size. Any clue what's causing this?Saritasarkaria
I added a little code-snippet in the form's load event to size the pbox to that of the image set on it. If image is set from another place, of course just move the code to there.Churchy
@GregWillard I can be a rounding error problem. the other way to do this, instead of using Scale(), calculate the Size directly using the variable. I will test to confirm and if, update my answer with that code instead.Churchy
I have updated my original post to see if maybe that code is causing the problem. Thanks and let me know. :)Saritasarkaria
I have updated the code with a different approach which seem stable.Churchy
I use the updated more robust code, still starts out the same (halfsize) but when I scroll now, the picture just disappears all together! :(Saritasarkaria
Ok, new update - increments back to not using e.Delta as it's probably due to different mouse sensitivities (I use a laptop pad, mouse wheels tend to be more sensitive). Implemented progressive zoom instead. See if this works.Churchy
I'm using a laptop pad too, I updated again to the latest code but still same problem. I have the picture box size property set to 600, 500 which is the original picture size however I am painting it with the graphics drawing object using 1000, 950 to make it larger. Could this have anything to do with it? When I try to scroll it just disappears altogether now. The picture will show up tiny if the size mode property is changed from normal to something else. Thank you for your continued help. All property with panel and picturebox are set as you have assumed before posting code.Saritasarkaria
I am unable to reproduce this problem. What you can do is to disable the custom image drawing and just test the picturebox with a simple picture and see if the problem still is present. If not then if need to be somewhere else. I don't think the problem is the different size as setting the Image property with remove the old and internally the new size is updated (but not shown if size mode is set to stretch etc).Churchy
Handles PictureBox1.MouseWheel is better than Handles Form1.MouseWheel imoRenatarenate
C
0

basically, you need an image viewer. I used this before: http://cyotek.com/blog/creating-a-scrollable-and-zoomable-image-viewer-in-csharp-part-4

it works great. however, it is an user control.

for picturebox, you need create graphics from the image, and then interpolation it. here is an example: http://www.dotnetcurry.com/ShowArticle.aspx?ID=196

I did not check this one, but looks like will work.

Cavafy answered 21/11, 2012 at 15:57 Comment(3)
Thanks for the reply, but I am looking to accomplish this in VB.NET and without using a third party control.Saritasarkaria
check the 2nd link, it has both c# and vb code. and it is for picturebox, but I did not try it before.Cavafy
I saw it, it's a good example, however I'm looking for an example scrolling with the mouse wheel and not the zoom slider. thanks!Saritasarkaria
U
0

I noticed that there's an undesirable effect with the StretchImage SizeMode that ignores the image ratio. I just added a width and height ratio variable to include in the "zoom" algorithm. See _ratWidth and _ratHeight in code below.

Public Class Form1

Private _originalSize As Size = Nothing
Private _scale As Single = 1
Private _scaleDelta As Single = 0.0005
Private _ratWidth, _ratHeight As Double

Private Sub Form_MouseWheel(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel

    'if very sensitive mouse, change 0.00005 to something even smaller   
    _scaleDelta = Math.Sqrt(PictureBox1.Width * PictureBox1.Height) * 0.00005

    If e.Delta < 0 Then
        _scale -= _scaleDelta
    ElseIf e.Delta > 0 Then
        _scale += _scaleDelta
    End If

    If e.Delta <> 0 Then _
    PictureBox1.Size = New Size(CInt(Math.Round((_originalSize.Width * _ratWidth) * _scale)), _
                                CInt(Math.Round((_originalSize.Height * _ratHeight) * _scale)))

End Sub

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

    'init this from here or a method depending on your needs
    If PictureBox1.Image IsNot Nothing Then
        _ratWidth = PictureBox1.Image.Width / PictureBox1.Image.Height
        _ratHeight = PirctureBox1.Image.Height / PictureBox1.Image.Width
        PictureBox1.Size = Panel1.Size
        _originalSize = Panel1.Size
    End If
End Sub
End Class
Unfledged answered 28/5, 2015 at 19:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.