Share via


Zooming image in a PictureBox control causes the PictureBox to move on the form

Question

Saturday, April 28, 2018 10:31 PM

Hello, all.  When dinosaurs ruled the Earth and Windows NT 4 was "new technology", I was an MCSE and a programmer in VB6.  I've moved to other things in life (I've not done any real coding in about 5 years and that was in VB6) but decided to write a specific program for myself and, wow, hasn't the technology changed a bunch?  Visual Studio Visual Basic 2017 is not VB6.  I say all that about my past to explain how I understand a lot of this stuff (form width, height, pixels, variables, subs and so forth), and yet cannot get some simple stuff to work properly.

I put a PictureBox control on a form and grabbed some code here to zoom the displayed image based on the MouseWheel event.  What happens, though, is that as I zoom in and out, the Left position of the PictureBox changes.  I update the titlebar with the left and right positions and it indicates "30 - 30" at each update of the zoom, but the image (PictureBox) moves from left to right as I zoom in and out.

I've checked the Form width and height; they do not change during the zoom operations.  I've checked the PictureBox width and height and they do change.  Since we're measuring from the left and the top for the properties of the PictureBox, I would think the box would just get taller and wider, but keep the same distance from the left and the top of the form.

Can someone tell me if I'm doing something stupid, please?  Thank you.

Here's zoom code:

Private Sub PictureBox1_MouseWheel(ByVal sender As System.Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseWheel
        If e.Delta <> 0 Then
            If e.Delta <= 0 Then
                If PictureBox1.Width < 250 Then Exit Sub 'minimum 50?
            Else
                If PictureBox1.Width > 1000 Then Exit Sub 'maximum 500?
            End If
            PictureBox1.Width += CInt(PictureBox1.Width * e.Delta / 1000)
            PictureBox1.Height += CInt(PictureBox1.Height * e.Delta / 1000)

            PictureBox1.Left = PictureBoxLeft
            PictureBox1.Top = PictureBoxTop

            Me.Text = CStr(PictureBox1.Left) & " - " & CStr(PictureBox1.Top)
            'Me.Text = CStr(PictureBox1.Width) & " - " & CStr(PictureBox1.Height)
            'Me.Text = CStr(Me.Width) & " - " & CStr(Me.Height)

        End If

All replies (12)

Saturday, April 28, 2018 10:49 PM

Where does (PictureBoxLeft) get set in your code.  That seems to be the only part I see in that code that sets the Left location of PictureBox1.  Have you tried just setting that to a fixed value to see if it moves?

 PictureBox1.Left = PictureBoxLeft

'maybe just try a fixed value to test it and see if it moves...

 PictureBox1.Left = 10 'or whatever number

If you say it can`t be done then i`ll try it


Saturday, April 28, 2018 10:53 PM

Hello, all.  When dinosaurs ruled the Earth and Windows NT 4 was "new technology", I was an MCSE and a programmer in VB6.  I've moved to other things in life (I've not done any real coding in about 5 years and that was in VB6) but decided to write a specific program for myself and, wow, hasn't the technology changed a bunch?  Visual Studio Visual Basic 2017 is not VB6.  I say all that about my past to explain how I understand a lot of this stuff (form width, height, pixels, variables, subs and so forth), and yet cannot get some simple stuff to work properly.

I put a PictureBox control on a form and grabbed some code here to zoom the displayed image based on the MouseWheel event.  What happens, though, is that as I zoom in and out, the Left position of the PictureBox changes.  I update the titlebar with the left and right positions and it indicates "30 - 30" at each update of the zoom, but the image (PictureBox) moves from left to right as I zoom in and out.

I've checked the Form width and height; they do not change during the zoom operations.  I've checked the PictureBox width and height and they do change.  Since we're measuring from the left and the top for the properties of the PictureBox, I would think the box would just get taller and wider, but keep the same distance from the left and the top of the form.

Can someone tell me if I'm doing something stupid, please?  Thank you.

Here's zoom code:

Private Sub PictureBox1_MouseWheel(ByVal sender As System.Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseWheel
        If e.Delta <> 0 Then
            If e.Delta <= 0 Then
                If PictureBox1.Width < 250 Then Exit Sub 'minimum 50?
            Else
                If PictureBox1.Width > 1000 Then Exit Sub 'maximum 500?
            End If
            PictureBox1.Width += CInt(PictureBox1.Width * e.Delta / 1000)
            PictureBox1.Height += CInt(PictureBox1.Height * e.Delta / 1000)

            PictureBox1.Left = PictureBoxLeft
            PictureBox1.Top = PictureBoxTop

            Me.Text = CStr(PictureBox1.Left) & " - " & CStr(PictureBox1.Top)
            'Me.Text = CStr(PictureBox1.Width) & " - " & CStr(PictureBox1.Height)
            'Me.Text = CStr(Me.Width) & " - " & CStr(Me.Height)

        End If

Hi

Using this (based on your code), seems not to show the effect you mention. In fact, I couldn't get anything to show that effect.

  Private Sub PictureBox1_MouseWheel(ByVal sender As System.Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseWheel

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

    Text = CStr(PictureBox1.Left) & " - " & CStr(PictureBox1.Top) & " - " & CStr(PictureBox1.Width)
  End Sub

Regards Les, Livingston, Scotland


Saturday, April 28, 2018 10:54 PM

I put a PictureBox control on a form and grabbed some code here to zoom the displayed image based on the MouseWheel event.  What happens, though, is that as I zoom in and out, the Left position of the PictureBox changes.

If the image is repositioned within the picture box control, that is associated with the SizeMode property.   As the size of the picture box is changed the relative position of the image within the picture box is recalculated according to that setting.

If you don't want the image to move within the picture box control then you need to create an image that fills the control by cropping the portion of the original image to exactly what you want to show.  Then use a size mode setting of Normal.


Saturday, April 28, 2018 11:15 PM

Set the PictureBox to have single or 3d borders so you can see if the borders are moving. I don't see how in your code that the PictureBox would move at all.

Nor do I understand how you believe enlarging the PictureBox will zoom the image.

If the image is a BackgroundImage in the PictureBox and the PictureBox's BackgroundImageLayout is set to zoom then as the PictureBox gets larger and smaller so will the image but you don't display code for those properties.

Perhaps there is other code in a paint event for the PictureBox altering its location. Is that all the code you have that sets the top and left of the PictureBox?

La vida loca


Sunday, April 29, 2018 12:35 AM

Thanks for the reply, IronRazerz.

<deleted irrelevant reply from me>

Okay, in the process of replying to you and testing it your way, just in case...I thought about how to show you and others what I was dealing with.  For grins, I put a border around the PictureBox and tried the zoom in and out.  It stayed fixed at the upper left.  Hmmmm, loaded an image in the Box and, BAM! it was centered.  The PictureBox was sized according to the height of the image and maintaining the aspect ratio for the left and right meaning it had a huge curtain on each side.  DOH!

The PictureBox control is staying where it's supposed to, the image just gets a larger column box (?) on each size (it's a Portrait-shaped image).

Thanks again for your reply.  You helped me work it through.  I just need to size the control differently.

--HC


Sunday, April 29, 2018 12:36 AM | 1 vote

There are lots of ways to do things of course.

Here is an example that centers mouse wheel zooming at the current mouse pointer position and you can also drag the image with LMB.

Do that in vb6!   :)

Public Class Form7
    Private WithEvents Pic1 As New PictureBox With {.Parent = Me, .Dock = DockStyle.Fill}
    Private Corner As New PointF(0, 0)
    Private MouseDownPt, MouseMovePt, MouseDownCornerPt As New PointF
    Private SourcePic As New Bitmap("c:\bitmaps\rusty.jpg")
    Private ScaleWidth As Double = SourcePic.Width
    Private ScaleRatio As Double

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load
        Text = "MW Zoom - LMB Drag"
        Form2_Resize(0, Nothing)
    End Sub

    Private Sub Form2_Resize(sender As Object, e As EventArgs) Handles Me.Resize
        SetScaleRatio(New MouseEventArgs(0, 0, 0, 0, 0))
        Pic1.Invalidate()
    End Sub

    Private Sub Pic1_Paint(sender As Object, e As PaintEventArgs) Handles Pic1.Paint

        With e.Graphics
            .Clear(Color.White)
            .SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            Dim sf As Single = CSng(Pic1.ClientRectangle.Width / ScaleWidth)
            .ScaleTransform(sf, sf)
            .TranslateTransform(-Corner.X, -Corner.Y)

            .DrawImage(SourcePic, New Rectangle(0, 0, SourcePic.Width, SourcePic.Height))

        End With
    End Sub

    Private Sub Pic1_MouseDown(sender As Object, e As MouseEventArgs) Handles Pic1.MouseDown
        MouseDownPt = e.Location
        MouseMovePt = e.Location
        MouseDownCornerPt = Corner
    End Sub

    Private Sub Pic1_MouseMove(sender As Object, e As MouseEventArgs) Handles Pic1.MouseMove
        MouseMovePt = e.Location

        If e.Button = MouseButtons.Left Then
            'drag the screen
            Dim sf As Double = Pic1.ClientSize.Width / ScaleWidth
            Dim x As Integer = CInt(MouseDownCornerPt.X - ((MouseMovePt.X - MouseDownPt.X) / sf))
            Dim y As Integer = CInt(MouseDownCornerPt.Y - ((MouseMovePt.Y - MouseDownPt.Y) / sf))
            Corner = New Point(x, y)
            Pic1.Invalidate()
        End If
    End Sub

    Private Sub Pic1_MouseWheel(sender As Object, e As MouseEventArgs) Handles Pic1.MouseWheel
        SetScaleRatio(e)
        Pic1.Invalidate()
    End Sub

    Private Sub Pic1_MouseEnter(sender As Object, e As EventArgs) Handles Pic1.MouseEnter
        If Not Pic1.Focused Then Pic1.Focus()
    End Sub

    Private Sub SetScaleRatio(e As MouseEventArgs)
        Dim x, y, s2 As Double
        Dim w As Double = ClientSize.Width
        Dim s As Double = CSng(ScaleWidth)

        If ScaleRatio <> 0 Then
            'calc mouse position in scaleunits
            x = Corner.X + (e.X * ScaleRatio)
            y = Corner.Y + (e.Y * ScaleRatio)

            'calc new scale and view centered on mouse position
            s2 = s - (Math.Sign(e.Delta) * s / 12)
            ScaleRatio = s2 / w
            ScaleWidth = s2
            Corner.X = CSng(x - (e.X * ScaleRatio))
            Corner.Y = CSng(y - (e.Y * ScaleRatio))
        Else
            ScaleRatio = s / w
        End If
    End Sub
End Class

Sunday, April 29, 2018 1:47 AM

There are lots of ways to do things of course.

Here is an example that centers mouse wheel zooming at the current mouse pointer position and you can also drag the image with LMB.

Do that in vb6!   :)

Nice. Now if only you could draw the mouse wheel rotating as you can draw the Cursor and circle on mouse down for dragging! ;)

La vida loca


Sunday, April 29, 2018 4:06 AM

First, thanks for your reply.

Second, I left out a bit of code which seems to make it work which would be:

Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        PictureBox1.Select()  'probably deselect in leave
    End Sub

Finally, I found the problem to be that the PictureBox shows the image in Portrait format including "empty" bars on the right and left.  What I was seeing was the image appear to move because the blank columns on either side were changing size.  Putting a box (BorderStyle = FixedSingle) around the PictureBox showed this.

The PictureBox was staying where it was supposed to.

Thanks again.

--HC


Sunday, April 29, 2018 4:11 AM

Thanks for the reply.  Yes, the image was repositioned in the PictureBox.  The image, in a Portrait layout, had deadspace left and right which scaled and appeared to make the control move.  I put a border around the PictureBox control and found this.  Oops.  My bad.

--HC


Sunday, April 29, 2018 4:14 AM

LaVidaLoca, yes, the borders helped.  In my attempts to reply to the first responder's post, I found this.  The border showed me that the control was not moving, just the deadspace "curtains" were changing size, too.

--HC


Sunday, April 29, 2018 2:16 PM

LaVidaLoca, yes, the borders helped.  In my attempts to reply to the first responder's post, I found this.  The border showed me that the control was not moving, just the deadspace "curtains" were changing size, too.

--HC

HC,

If your question has been answered then please close the thread by selecting the post(s) that helped using the Select as Answer link at the bottom of the post. Mark any helpful posts you liked as well.

Furthermore, There are settings which affect how the image is placed on the picturebox ie Zoom, Stretch. You will see different results depending on the setting.

https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k%28System.Windows.Forms.Control.BackgroundImageLayout%29%3Bk%28TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2%29%3Bk%28DevLang-VB%29&rd=true&f=255&MSPPError=-2147217396

https://msdn.microsoft.com/en-us/library/system.windows.forms.imagelayout(v=vs.110).aspx


Sunday, April 29, 2018 5:15 PM

Nice. Now if only you could draw the mouse wheel rotating as you can draw the Cursor and circle on mouse down for dragging! ;)

La vida loca

 That would be my department.  That circle is drawn by my Gif Creator program when a mouse button is detected as being pressed while the screen capture method is capturing the screen.  Maybe at some point I will try using a different method to handle the mouse activity better.  Maybe even add keyboard activity too.  I just have too much stuff to keep up with at this point in time.   8)

If you say it can`t be done then i`ll try it