# VBForums CodeBank > CodeBank - Visual Basic .NET >  ZoomPictureBox: picture control with mouse-centred zooming

## boops boops

New version February 2019. See post #75 for details and zip files, and post #79 for a testing procedure.. The new version works much better with* large images* and includes a *DragMargin* property to prevent the image from being dragged out of view. 

*Introduction*

This control offers easy zooming and dragging of any image. Out of the box, you can zoom the image with the mouse wheel and drag it with the left mouse button. But you can implement other ways of zooming and dragging in your code. 

To whet your appetite, here's an illustration from the test project in the zip file:


The ZoomPictureBox has three different zoom modes. You can zoom to the centre of the control, to the centre of the image or to the mouse position. The last is my own favourite, so I have made it default. 

You can set Image and the ZoomMode in the Designer or in your code. There are some other useful variables you can presently set only in your code. These include the minimum and maximum zoom sizes, and the MouseWheelDivisor which affects zooming speed with the mouse.

If you want to use some other way of controlling zoom, say a + and - button, set the control's EnableMouseWheelZooming to False, and change the ZoomFactor property in your code. The same applies to dragging; if required set EnableMouseDragging to false and implement some other way of dragging, for example with the arrow keys. In your code, you can move the image by setting the ImagePosition property.


*Technical notes*

1. I started off by inheriting from a PictureBox which explains the name. But I changed that later to a UserControl to save exposing unnecessary properties such as SizeMode and ImageSource. 

2. The control works by changing the size and position of a rectangle (_ImageBounds). The image is rendered into the rectangle in the OnPaint sub.

3. Quite a few of the public fields could be usefully turned into properties which could be set in the designer. I will do that later that if there is enough interest.

4. The attached zip file is a complete solution (without the obj and bin folders and the dll file). It includes a demo Forms project. You should be able to unzip all the files and run the demo (I hope).

5. You can copy the ZoomPictureBox.vb file (in the ZoomPictureBox_Source folder) to use the control in your own projects.

6. Alternatively, you could give the ZoomPictureBox a permanent place in your ToolBox complete with its own icon . To do that: 
a. check that the bitmap ZoomPictureBox.bmp has its Properties/Build Action set to Embedded Resource.
b.  build the project
c. right click in the ToolBox and select Insert Items....
d. browse to the ZoomPictureBox_Build folder and select ZoomPictureBox.dll.

----------


## wej0901

Do you have a version of the subject ZoomPictureBox code in VS 2005?

----------


## boops boops

I built it using VB2010 with VB2008 in mind. I don't think there's anything in the code that won't compile under VB2005, but I don't have a copy to try it out. If nothing else helps I'm sure you could copy the all .VB files and the icon bitmap across to a new solution. The solution should have a Windows Forms project for the TestForm and a Class Library project for the rest. Make sure the Class Libary has references to System.Windows.Forms and System.Drawing. (You might need to reference System.ComponentModel as well, but I think it's included in Forms.) Maybe someone else knows an easier way. BB

----------


## .paul.

@Boops. I converted it to vb2005. There's an error creating the form when you try to run the project with image = none + also the image remains displayed when you remove it at design time. Any idea what the problem is? Great control though.

----------


## boops boops

Thanks for pointing out the problems Paul. I think I know how to fix them. I need to add


```
If _Image Is Nothing Then Return Rectangle.Empty
```

at the top of the GetZoomedBounds function, which otherwise needs the size of the image to do its work. 

As for the image not clearing at design time, I can't reproduce the problem but I think I can see what might cause it. In the InitializeImage sub, I need to move Me.Invalidate outside the If _Image IsNot Nothing block so that the control will also be invalidated when the image is cleared. 

I'll check these and if possible update the zip file tomorrow.

BB

----------


## .paul.

yeah that fixed it. here's a vb2005 version for you:

*edit:* updated all points in post #7 + post #10

----------


## boops boops

I've updated the zip file in Post #1 with a few corrections and improvements. If you've added the control to your toolbox, please delete it then follow the steps in Post #1 (6a to 6d) again to reinstall it. 

@.Paul. Would you be so kind as to update the VB2005 version?


Changes in ZoomPictureBox.vb:
1. Superfluous Imports statements removed.
2. Superfluous Shadows keyword removed from Image property.
3. In the ZoomFactor.Set, limited invalidation to the "before" and "after" rectangles. This improves performance when the BackgroundImage is set.
4. Ditto, in OnMouseMove sub.
5. In the InitializeImage sub, moved Invalidate outside the If block (see post #4).
6. In the GetZoomedBounds function, checked for existence of Image (see post #4).

New toolbox icon:

A bit more elegant, I hope you'll agree.

Changes in TestForm:
ZoomPictureBox.Anchor property set to "all sides" in Load event.

EDIT:  I'm now unsure if the first version of the zip file actually included the test form. Well it does now!

----------


## wej0901

I must be doing something wrong.  I am running the VS2005 in debug mode and I am getting the following User Interface that is displayed within the attached file.  Please help.  Thank you.  Bill

----------


## wej0901

Sorry for the bother. I've got it working.  Very Cool Application.  I will definitely add this to my library.  I've been developing VB.net application for slightly over a year now.   I am only a babe in the woods compared to you folks.  My latest application was pretty intense mechanical engineering application for balancing the flow through a steam turbine and using a Newton-Raphson numerical method.   I have a great understanding for the mathematics but with VS it is so complex and overwhelming at times.  Thank God for the internet.

----------


## boops boops

> yeah that fixed it. here's a vb2005 version for you:
> 
> *edit:* updated all points in post #7 except the onMouseMove change because the image doesn't drag smoothly


Many thanks for the updated vb2005 version. I'm worried about the image not dragging smoothly, because I intended the changes to fix exactly that problem. Here's my current version of the OnMouseMove sub, in case you didn't get it from the latest zip file:



```
	Protected Overrides Sub OnMouseMove(e As System.Windows.Forms.MouseEventArgs)
		If _dragging Then
			Me.Invalidate(_ImageBounds) 'old position
			_ImageBounds.X += e.X - _startDrag.X
			_ImageBounds.Y += e.Y - _startDrag.Y
			_startDrag = e.Location
			Me.Invalidate(_ImageBounds) 'new position
		End If
		MyBase.OnMouseMove(e)
	End Sub
```

If this doesn't fix it, would you please give me some more information. What is the size of the Image and BackgroundImage, and do they have (partly) transparent pixels? Are they photos or drawings? What is the size and BackgroundImageLayout of the ZoomPictureBox? Finally, it would help to know about your system: memory, graphics subsystem etc.

regards, BB

----------


## .paul.

ok Vic. i hadn't tested it, but yes it works with your last mod. i've updated the zip for you.

thanks again for posting it. i couldn't get my head round the resizing/positioning :Big Grin:

----------


## LDeeJay

This is a great control. Gives me lots of possibilities... however... (why is there always one.. ?)

I've turned the vb into a dll and added to my app (vb2008). Now when I place the control on a form at default, location 0.0 it all works fine. When I move the control on the form, the mouse-focus shifts exponentially. So when I place the control on position 100.100 (size 200x200), I must use the mouse between 200.200 and 400.400 to zoom the image. 

It's not the size of the control on the form, it's focused around the upper left position of the control, the mouse focus always starts twice the distance from the upper left position of the control. So the closer you keep it to the 0.0 of your form, the bigger the chances that you can keep your mouse on the image to scroll. 

Any idea what I'm doing wrong? Is it a setting or a parameter I'm overlooking?

Cheers,

----------


## boops boops

Hi LDeeJay, welcome to VB forums. It's way past bedtime where I am, so I'll have a think about your problem tomorrow. Which mouse zooming mode are you using -- zoom to mouse position (the default), zoom to centre of image or zoom to centre of control? 

BB

----------


## LDeeJay

Bonjour/Goedemorgen Boops Boops, 

Yeah, way past bedtime here as well....  :Embarrassment:  And although I'm a member for 10 years now, I could always cope with just lurking  :Cool: 

Any mode. It all has the same result. Funny enough, the panning works ok, it's just the zooming (or scroll wheel if you like). 

Maybe related, maybe not, I sometimes get an Overflow Exception on this line: 

```
_ImageBounds.Width = CInt(_ImageBounds.Width * zoomRatio)
```

 saying that an 


> Arithmetic operation resulted in an overflow.


I'm just opening the same pictures again and again... I haven't been able to pinpoint that one to a certain action or event, it seems a bit random at the moment. 

Cheers,

L&#233;on

----------


## boops boops

Hi L&#233;on,

I just downloaded my own zip from post #1 and the zooming error you encountered is there large as life -- even in the test program! So thanks a lot for point it out. It's stupid I didn't notice it before (but neither did the 180 or so people who downloaded the code so far, or they didn't feel inclined to report it.)  I will post a corrected version as soon as I have made sure it works correctly.

I'm puzzled by your other problem. I can cause an Overflow Exception by disabling the ZoomFactor validation and setting the MouseWheelDivisor to 1; but that's at a zoom factor of about 4 million. I assume you are not trying anything like that, but to be sure can you say what values you have for Image.Width and ZoomFactor (hover the mouse over the variable names when the error is thrown)?

BB

----------


## LDeeJay

Zooming in and out works fine. At some point you can't zoom any further and that's fine. When the error occurs (most of the time just after starting the app), I haven't done any zooming/panning yet. The image is being loaded (an attempt is made) and at the moment it tries to stretch it in the control, it crashes. 

The values: 
_Image.Width=3872
_ImageBounds.Width = 0
-ImageBounds.Height=0
_ZoomFactor=0.077479338842975212
PreviousZoomFactor=0.0
zoomRatio=1.#INF

----------


## boops boops

> Zooming in and out works fine. At some point you can't zoom any further and that's fine. When the error occurs (most of the time just after starting the app), I haven't done any zooming/panning yet. The image is being loaded (an attempt is made) and at the moment it tries to stretch it in the control, it crashes. 
> 
> The values: 
> _Image.Width=3872
> _ImageBounds.Width = 0
> -ImageBounds.Height=0
> _ZoomFactor=0.077479338842975212
> PreviousZoomFactor=0.0
> zoomRatio=1.#INF


Thanks. I can't reproduce the Overflow problem but your data has been helpful in taking a fresh look at the ZoomPictureBox code. I hope I have now made it more robust. Would you be so kind as to add the attached vb file to your project, rebuild and then try it instead of the existing ZoomPictureBox. Does it solve the overflow problem?

Meanwhile, I am still hunting for the cause of the mouse position problem. As far as I can see the only problem is that the wrong rectangle is raising MouseWheel events for the control. I have no idea why, so this may take a little time :Frown: .

By the way, the maximum zoom factor is set to 32, but you can change it to any value. In the next version I will expose it as a Public Property.

BB

----------


## boops boops

The mousewheel problem is solved. What else could it be but the test in OnMouseWheel?


```
If EnableMouseWheelZooming AndAlso _
Me.Bounds.Contains(Me.PointToClient(MousePosition)) Then ...
```

Me.Bounds should have been Me.ClientRectangle. And PointToClient(MousePosition) can be replaced by e.Location. Credit to LDeeJay who spotted the problem at around the same time (private mail). I'll post a cleaned up version of the code soon.

BB

----------


## LDeeJay

Fantastic job! Now on to my next challenge :-)

I want to zoom several images, which I can do now, and copy the contents of these controls into a new image. I can create a destination picture but... not with the result I want. 

I've played around with FastPix, BitBlt and GetPixel but they all give me the result of the original picture that's loaded in ZoomPictureBox, not the zoomed picture so.... how can I copy the result of ZoomPictureBox into a new image?

Can anyone push me in the right direction? I'm using vb.net 2008.

Thanks.

----------


## .paul.

try the graphics class method, CopyFromScreen

----------


## LDeeJay

Fantastic! Although not quite as nice as being able to get the controls result right away, I've managed to get the images nicely copied. 

Disadvantage is that the images cannot be covered by anything and can't be hidden before the capture has taken place. Nevertheless... result!

Thanks again!

----------


## boops boops

There is another method capturing the image of a control as shown, the control's DrawToBitmap method, which works even when the control is partly or wholly hidden. However, I think that in the long run it is better to work as much as possible with the original images. The main reason is that the resolution is otherwise limited by the size of the controls, so you could lose quality when you work with larger images. 

It's not difficult to superimpose one image on another without resorting to BitBlt etc. just by using DrawImage. The SuperimposeImage sub in the code below is an example. The ImagePosition and ZoomFactor properties of the ZoomPictureBox are useful here, as I intended. It takes a lot more work to get that kind of information from a normal picture box.

Anyway, to cut a long story short I decided to work out a little demo program for composing images. It could do with a lot of refinement but it should give you the idea. To use the code, start a form and add three buttons, a Picturebox and a ZoomPictureBox. Don't bother about setting the size or other properties of the two boxes because that is all dealt with in the code.

In use, Button1 opens a base image which is shown at full size; click cancel if you want an empty bitmap. Button 2 opens a zoomable/draggable image. *Double-click* the zoomed image to paint it onto the base image. Button3 saves the resulting image as a PNG or JPEG. 

Here's a picture of the demo use:


And here's the code for the form:

vb Code:
Private _BaseImage As Image    Private _AddImage As Image     Public Property EmptyBitmapSize As New Size(500, 500)     Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load        PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize        PictureBox1.BorderStyle = BorderStyle.Fixed3D        ZoomPictureBox1.Parent = PictureBox1        ZoomPictureBox1.BackColor = Color.Transparent        ZoomPictureBox1.BorderStyle = BorderStyle.None        ZoomPictureBox1.Bounds = PictureBox1.ClientRectangle    End Sub     'Keep the ZoomPictureBox aligned to the PictureBox:    Private Sub PictureBox1_SizeChanged(sender As Object, e As System.EventArgs) Handles PictureBox1.SizeChanged        ZoomPictureBox1.Bounds = PictureBox1.ClientRectangle    End Sub     Private Sub ZoomPictureBox1_DoubleClick(sender As Object, e As System.EventArgs) Handles ZoomPictureBox1.DoubleClick        PictureBox1.Image = SuperimposeImage(_BaseImage, _AddImage, ZoomPictureBox1.ImagePosition, ZoomPictureBox1.ZoomFactor)    End Sub     'Get the base image for the PictureBox (or an empty bitmap)    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click        _BaseImage = GetImage(EmptyBitmapSize, "Select base image")        PictureBox1.Image = _BaseImage    End Sub     'Get a image for the ZoomPictureBox    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click        _AddImage = GetImage(EmptyBitmapSize, "Select zoomable image")        ZoomPictureBox1.Image = _AddImage    End Sub     'Save the resulting image    Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click        SaveImage(_BaseImage)    End Sub     'Get an image from file or an empty bitmap:    Private Function GetImage(emptyBitmapSize As Size, caption As String) As Image        Dim bmp As New Bitmap(emptyBitmapSize.Width, emptyBitmapSize.Height)        Using ofd As New OpenFileDialog With {.Title = caption}            If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then                Try                    bmp = New Bitmap(ofd.FileName)                Catch                    MessageBox.Show("Invalid image file " & ofd.FileName)                End Try            End If        End Using        Return bmp    End Function     'Superimpose an image on the base image at a given position and magnfication:    Private Function SuperimposeImage(baseImage As Image, addImage As Image, location As Point, zoomFactor As Double) As Image        Using g As Graphics = Graphics.FromImage(baseImage)            g.DrawImage(addImage, location.X, location.Y, _              CInt(addImage.Width * zoomFactor), _              CInt(addImage.Height * zoomFactor))        End Using        Return baseImage    End Function     'Save the resulting base image:    Private Sub SaveImage(img As Image)        Using sfd As New SaveFileDialog With {.Filter = "Image Files (*.png, *.jpg)|*.png;*.jpg"}            If sfd.ShowDialog = Windows.Forms.DialogResult.OK Then                If sfd.FileName.ToUpper.EndsWith("PNG") Then                    _BaseImage.Save(sfd.FileName, Imaging.ImageFormat.Png)                ElseIf sfd.FileName.ToUpper.EndsWith("JPG") Then                    _BaseImage.Save(sfd.FileName, Imaging.ImageFormat.Jpeg)                Else                    MessageBox.Show("Please give a PNG or JPG extension. Other formats are not yet supported.")                End If            End If        End Using    End Sub

@.Paul. I hope you'll try it too.

BB

----------


## boops boops

New version of ZoomPictureBox 20 January 2012. See post #22 above for info on the BB Image Composer demo application. Downloads are in post #1.

*Summary of changes*
_Bugs Fixed:_ 
- Corrected faulty rectangle for detection of mouse wheel action.
- Code revised to prevent potential integer overflow.

_New:_
- New public read only property: ImageBounds. 
- All public fields are now exposed as properties.
- Default values for MaximumZoom and Minimum Image Width/Height are changed.
- New demo application: BB Image Composer (see post #22 for details).

_Technical modifications:_
- The TestForm and demo application are placed in separate projects from the ZoomPictureBox itself.
- To keep the file sizes convenient, the ZoomPictureBox Class is split into two Partial Classes. One contains all the properties, the other everything else.
- The solution with demo is built in VB2005 and converts without change when loaded into VS2008 or VS2010.

I hope you like it! BB

----------


## panesian2000

Fantastic job! These is a great control. Has just permanent place it in my ToolBox and bookmark this thread. Thanks

----------


## boops boops

Hi Panesian, 

Welcome to the VB Forums and thanks for your kind words. If you have questions (unless they are specifically about the ZoomPictureBox) please post them on the VB.Net forum.

BB

----------


## SteveHeather

Hi BB, I am new to this forum and to VB.NET, your application is brilliant. I am going to ask a question which is probably dumb, but I have to ask.

I start the BB Image Composer app, click on 'Open Base Image', I search for the picture I require, which is landscape picture of my daughter, it places the picture in app but I only see a small portion of the picture. The picture dimensions are; 4216 x 2968. So it is a large picture. What if any, do I need to do to get this particular picture to fit in the viewer?

Sorry if it sounds a dumb question but I just don't know.

Thank you,

Steve.

----------


## boops boops

Hi Steve,

In Load sub of the ImageComposer, I set the SizeMode of the base PictureBox (PictureBox1) to AutoSize. That means the picture box has the same size as the image. I did that to keep things simple -- after all, I meant it just a demo of how you can use a ZoomPictureBox, not a full-fledged application. Unfortunately, it's not much use for large images like your photo.

A simple answer is to use a smaller version of your photo. You could replace the first line of the Button1 Click sub by these lines:


```
Dim img As Image = GetImage(EmptyBitmapSize, "Select base image")
_BaseImge = New Bitmap(img, width, height)
```

Enter whatever positive values you like for _width_ and _height_. It would be neater to declare the width and height as public properties so you can change them in the Designer (see the EmptyBitmapSize property for an example).

I'd like to redesign the whole program so that you could use different picture box size modes, or even another ZoomPictureBox for the base image. But that would make it quite a bit more complicated so it will have to wait for the while :Smilie: .

BB

----------


## SteveHeather

Thanks for your help, yes I will look at your suggestions, I can imagine how much more work would be involved. But yes the image is way too large, I will certainly reduce it's size.

Thanks BB.

----------


## panesian2000

After loading the image into the object. Can i zoom in and display certain part of the image automatically.

----------


## boops boops

Yes, that's what the ZoomFactor and ImagePosition properties are for. You could set them in the form Load or a button Click sub, for example. 

Alternatively, you could take a snapshot of the part of the image you want to use by using the zoompicturebox's DrawToBitmap method:


```
		Dim zRect As Rectangle = ZoomPictureBox1.ClientRectangle
		Dim bmp As New Bitmap(zRect.Width, zRect.Height)
		ZoomPictureBox1.DrawToBitmap(bmp, zRect)
```

Then you could use bmp as the image for the zoompicturebox, another picture box etc.

I'll think about adding a Snapshot property based on the above code to the next version of the ZoomPictureBox control, if there is one.

BB

----------


## panesian2000

Can you show me some simple code? I cant get it work. My image size is (800,600), my zoompicturebox size is (200,50). How can i display my image at certain zoom level and also at certain location of my image.

----------


## boops boops

Try this in the Form Load sub or a Button Click sub. Play around with the numbers until you get the zoom size and position you want:


```
		
		ZoomPictureBox1.ZoomFactor = 0.4
		ZoomPictureBox1.ImagePosition = New Point(50, 60)

		'If you want to leave the image fixed in that position, add these lines:
		ZoomPictureBox1.EnableMouseWheelZooming = False
		ZoomPictureBox1.EnableMouseDragging = False
```

BB

----------


## panesian2000

Thanks. U really save my day.

----------


## jascard

Thanks 
how i stretch image

----------


## jascard

sorry my language is bad !

how i do zoomed stretched image  in zoompicturebox
thanks

----------


## boops boops

Hi jascard,
You could try this, for example when loading the form:


```
Dim s As Size = ZoomPictureBox1.ClientSize
ZoomPictureBox1.Image = New Bitmap(ZoomPictureBox1.Image, s.Width, s.Height)
```

Is that the effect you are looking for?

BB

----------


## jascard

Thanks for your help

----------


## OCD Dan

Boops,
          Thanks for the zoompicturebox, this is very usefull in my app, my users can enlarge blueprints to see details very well, any chance there's a way to print while the image is zoomed? Thanks again, this is really great control.

----------


## boops boops

You have your original image and you can get an enlarged detail as a separate image (see post #30). If you don't know how to print an image, please ask on the VB.Net forum. BB

----------


## jfrazier

How would I go about adding a zoom in and zoom out button in addition to the mouse scroll function?  For the standard picturebox, what I see people doing is just changing the size of the picturebox itself and I am trying to utilize the zoompicturebox here and add the button function to it without changing the size of the control every time.  I am really new to VB.net and this is part of what I am doing to learn the language.

----------


## boops boops

Hi jfrazier, welcome to the forums.

You can code the Click event subs of the buttons to change the ZoomFactor property. You could add/subtract to the present zoom factor or multiply/divide it; that's a matter of your own design. Alternatively you could use a number of buttons each to set a specific value of the ZoomFactor (1 means original image size).  As an example, suppose you add a "Zoom In" button to the form. Then double click the button and put this in its Click event sub (assuming the ZoomPictureBox is named zpb1):


```
zpb1.ZoomFactor * = 1.25
```

And you could put something similar but with a factor of say 0.75 in the "Zoom Out" button's Click sub. 

The scroll wheel zooming will still work as long as you don't change EnableMouseWheelZooming to False. If you are using ZoomMode "zoom to mouse position", that might look a little odd when you click a button to zoom. But it's easy to change the mode to CenterControl temporarily in the button's Click sub, for example:



```
	zpb1.ZoomMode = ZPBLibrary.ZoomPictureBox.ZoomType.ControlCenter
	zpb1.ZoomFactor *= 1.25
	zpb1.ZoomMode = ZPBLibrary.ZoomPictureBox.ZoomType.MousePosition
```

BB

----------


## jfrazier

Thank you.  That was much more simple than what I was trying unsuccesfully to do.  I was turning off the mouse control and then turning it back on, or at least that was what I was trying to do.  It wasn't working in the least, but this works like a charm. 

Many thanks from a .Net Newbie

----------


## jfrazier

I am trying to add zoom features to my program and I am doing a fit to width and fit to height click options.  I am getting the size working, but I am having no luck on moving the picture within the zoompicturebox on just the click.  I am attempting to get it to the upper left corner.  My research is showing that the picturebox would use sizemode, but as I am not inheriting from picturebox it is not present with zoompicturebox.  So far I have not found a combination that does what I am trying to do.  Any ideas?

Thank you,
newbie

----------


## boops boops

Try this:


```
ZoomPictureBox1.ImageLocation = Point.Empty
```

Point.Empty is the same as Point(0,0). With a little bit of arithmetic with the widths and heights you should be able to work out how to centre the image if you need to.

BB

----------


## fryed

What would keep the ZoomFactor property from updating?  When I load a new image into the ZoomPictureBox, I check the size of the control vs. the size of the image and depending on the aspect ratio I attempt to set the ZoomFactor to size the image so it is fit inside the control.  I attempt to use zoompicturebox.ZoomFactor = <some value> but the value is not updating.  For example:

Dim wRatio As Double = splContainer.Panel2.Width / zpbImage.Image.Width
Dim hRatio As Double = splContainer.Panel2.Height / zpbImage.Image.Height
        If wRatio < hRatio Then zpbImage.ZoomFactor = wRatio Else zpbImage.ZoomFactor = hRatio

----------


## jfrazier

try zpbImage.Refresh() after what you have.

----------


## fryed

> try zpbImage.Refresh() after what you have.


Sorry, I did have the refresh method in there, it somehow got cut off when I pasted the code in.  What is odd is that it works early on but after loading some images, resizing the form, or zooming in it will exhibit this behavior.  I'm sure I'm messing something up in my other code but I can't figure out what it might be.

This is an awesome control and is working really well for me except for this one little issue.

----------


## jfrazier

I have had to rig up a zoom of approximately 200%.  I'm still trying to get a firm grasp on the zoom factor property.

----------


## boops boops

> What would keep the ZoomFactor property from updating?  When I load a new image into the ZoomPictureBox, I check the size of the control vs. the size of the image and *depending on the aspect ratio I attempt to set the ZoomFactor to size the image so it is fit inside the control*.  I attempt to use zoompicturebox.ZoomFactor = <some value> but the value is not updating.


The ZoomPictureBox does that automatically when you set its Image property. So you shouldn't have to do anything at all.  




> For example:
> 
> Dim wRatio As Double = splContainer.Panel2.Width / zpbImage.Image.Width
> Dim hRatio As Double = splContainer.Panel2.Height / zpbImage.Image.Height
>         If wRatio < hRatio Then zpbImage.ZoomFactor = wRatio Else zpbImage.ZoomFactor = hRatio


I'm not sure how that works because I don't know what you are doing with splContainer.Panel2. But I suspect something is wrong with the logic. To fit an image to a box, what you need to do is this: If the picture is wider and flatter than the box, fit the image widthways. Otherwise fit it heightways. That's all! If you want a code  example, look in the ZoomPictureBox code for a function called FitImage (or something like that).

BB

----------


## fryed

> The ZoomPictureBox does that automatically when you set its Image property. So you shouldn't have to do anything at all.  
> 
> I'm not sure how that works because I don't know what you are doing with splContainer.Panel2. But I suspect something is wrong with the logic. To fit an image to a box, what you need to do is this: If the picture is wider and flatter than the box, fit the image widthways. Otherwise fit it heightways. That's all! If you want a code  example, look in the ZoomPictureBox code for a function called FitImage (or something like that).
> 
> BB


I made a simple test project with just a couple lines to add an image to the control and as you said, it fits it automatically without me having to do anything else.  I must've overthought it when writing my code and buggered something up in the process.  I'll have to go back and redo my stuff and simplify it.  Thanks for your help.

Dan

----------


## siglr

Hello
Regarding the mouse wheel event, I would suggest you change the way you "grab" focus to something more elegant, in the same way Outlook or Internet Explorer works.

You do this by first implementing the IMessageFilter interface like this:



```
Public Class ZoomPictureBox
    Inherits UserControl
    Implements IMessageFilter
```

Then you add this line in your constructor:



```
Application.AddMessageFilter(Me)
```

And the following method and declarations:



```
    Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
        If m.Msg = &H20A Then
            ' WM_MOUSEWHEEL, find the control at screen position m.LParam
            Dim pos As New Point(m.LParam.ToInt32() And &HFFFF, m.LParam.ToInt32() >> 16)
            Dim hWnd As IntPtr = WindowFromPoint(pos)
            If hWnd <> IntPtr.Zero AndAlso hWnd <> m.HWnd AndAlso Control.FromHandle(hWnd) IsNot Nothing Then
                SendMessage(hWnd, m.Msg, m.WParam, m.LParam)
                Return True
            End If
        End If
        Return False
    End Function

    ' P/Invoke declarations
    <DllImport("user32.dll")> _
    Private Shared Function WindowFromPoint(pt As Point) As IntPtr
    End Function
    <DllImport("user32.dll")> _
    Private Shared Function SendMessage(hWnd As IntPtr, msg As Integer, wp As IntPtr, lp As IntPtr) As IntPtr
    End Function
```

Then, the mouse wheel message is automatically sent to any control that is currently under the mouse pointer.

Thanks

----------


## boops boops

Hi siglr, welcome to VB.Forums. Thanks for your suggestion of using  a MessageFilter. I tried  your code and it seems to work well.

I wonder if we really need to find the window to send the  filtered message to? After all, the only window we are concerned with is that of the ZoomPictureBox instance itself. Then we could skip the WindowFromPoint function, and slim the PreFilterMessage function down to this:


```
Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
If m.Msg = &H20A Then 
   SendMessage(Me.Handle, m.Msg, m.WParam, m.LParam)
   Return True
Else
    Return False
End IfEnd function
```

It does appear to work as intended on a quick test.

However, I don't see why putting Me.Select in the OnMouseEnter should be considered less elegant. The effect is the same and it's certainly a lot shorter. Maybe you can convince me why I am wrong! I have to admit, on looking again at the code for the ZoomPictureBox, I overrode OnMove and OnSizeChanged with Me.Select, and put it in OnMouseDown too. I can't remember why I did that. Probably it was just some debugging effort I forgot to erase. Now _that's_ inelegant :Embarrassment: !

BB

----------


## siglr

Well, for our data-entry software, we don't want the focus moving out of the text input fields while the user works with the image (zoom or drag), so that's why it's important for the control not to grab the focus.

Also, the reason I need to find the control to send the message to, is that I have two controls that need to support mouse wheel events. So I need to send it to the right one (the one below the mouse pointer).

Thanks!

----------


## boops boops

Thanks for your explanation. I see your point about the TextBoxes. However, I don't think the MessageFilter code belongs in the ZoomPictureBox definition, because it affects the behaviour of other controls in the same application. Besides, if an application has multiple ZoomPictureBoxes, it would be inefficient to install a new filter with each instance. I guess it would be best to put the filter code on the startup Form (in a simple application) or, better, in a separate class. 

I admit my first point applies just as much to using Me.Select in the OnMouseEnter sub: it affects other controls, so it really shouldn't be there. But it's a simple fix which I think improves the ergonomics of the control. If I ever get round to a new version, I'll add a comment that it's a bit of a hack and should ideally be replaced by a proper message filter, with reference to your posts.

Thanks again,
BB

----------


## Ebro

how can use this functionality to c#. Thank you

----------


## boops boops

The ZoomPictureBox should work equally well in any Windows Form application, regardless of your programming language. 

So you could build the ZoomPictureBox Class using any Visual Studio version or VB.Net Express edition from 2005+. Then add the dll file to your ToolBox as explained in Post #1. 

Alternatively, you could run the code through a VB.Net to Csharp converter first. If necessary Google for an online or downloadable converter. Then add the class to your own project, or build it separately and add the dll to it the Toolbox as above.

BB

----------


## Ryan_Smith

Hi BB,
Thanks for the excellent zoom pic box control. I have applied it to a problem but need some further advice. 

I would like to click on the image in the ZPB and have it return the "image" x,y pixel coordinates, regardless of the zoomfactor or pan position.

Is there a way that the ZPB control could return those values ?  The aim is to zoom the image in on a feature and then click the mouse on the feature to get the position.

Any help would be greatly appreciated.

----------


## boops boops

Here's a function you can use to get the click point in image coordinates:


```
	Private Function ImagePoint(zpb As ZoomPictureBox, mousePoint As Point) As Point
		With zpb
			Dim dx As Integer = mousePoint.X - .ImagePosition.X
			Dim dy As Integer = mousePoint.Y - .ImagePosition.Y
			Dim zx As Integer = CInt(dx / .ZoomFactor)
			Dim zy As Integer = CInt(dy / .ZoomFactor)
			Return New Point(zx, zy)
		End With
	End Function

	'example of use of ImagePoint function:
	Private Sub ZoomPictureBox1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles ZoomPictureBox1.MouseDown
		Console.WriteLine(ImagePoint(ZoomPictureBox1, e.Location).ToString)
	End Sub
```

I'll make this a property of the ZoomPictureBox itself, whenever I get around to a new version :Embarrassment: .

----------


## Ryan_Smith

Thanks BB, that is exactly what I was after !

 :Smilie:

----------


## Ryan_Smith

Hi BB,
One other question, if I want to draw a graphic on the image, say a small circle at the click point on the image, how would you suggest this is done ? I would like the graphic to move with the image zoom/pan. Write to the pixel array or an overlay approach ?

----------


## boops boops

Hi Ryan, sorry I neglected your question. It's been a busy time for me. 

I think should be efficient enough to paint the superimposed image with Graphics.DrawImage (or draw the circle with Graphics.DrawEllilpse). See the SuperimposeImage function in the demo project for an example. I don't know whether using a pixel array to do the superimposition would have any advantage. My guess is that the difference probably won't be very much, and it may go one way or the other depending on the sizes of the images. 

BB

----------


## Goshx

line 82-83 in your demo

If sfd.FileName.ToUpper.EndsWith("PNG") Then
                    _BaseImage.Save(sfd.FileName, Imaging.ImageFormat.Png)


gives an error when I tried to save result image from PNG file:
Object reference not set to an instance of an object.

----------


## boops boops

> line 82-83 in your demo
> 
> If sfd.FileName.ToUpper.EndsWith("PNG") Then
>                     _BaseImage.Save(sfd.FileName, Imaging.ImageFormat.Png)
> 
> gives an error when I tried to save result image from PNG file:
> Object reference not set to an instance of an object.


The base image exists if you load one. Alternatively you can stamp the zoomable image on a blank background. Otherwise there isn't anything to save. 

The image composer is just a quick demo, not a full-fledged program. If you think it's necessary to check whether there is anything to save before you try to save it, add it to your own code.

BB

----------


## Goshx

Well... Playing with ImagePosition and ZoomFactor properties I've mentioned that they won't restore the same position as it was before. As higher zooming is as larger error we get.

----------


## boops boops

> Well... Playing with ImagePosition and ZoomFactor properties I've mentioned that they won't restore the same position as it was before. As higher zooming is as larger error we get.


Yes, the position does tend to drift slightly when you zoom in and out heavily. The formulas in the code are inevitably a bit approximate (for example because the mouse position doesn't map to an exact image pixel when the zoom factor is less than 1) but there may be something making matters worse than necessary. I hope to find some time to look into it soon. 

Meanwhile, I've spotted a rather stupid error in the ZoomPictureBox_Public Properties.vb file. The Set clause of the EnableMouseWheelZooming property should have
_EnableMouseWheelZooming = Value
instead of =True. That won't affect your problem, but it could be annoying for anyone trying to disable zooming with the mouse wheel :Embarrassment: .

BB

----------


## Goshx

:Smilie:  I wouldn't say it is slightly. First time when that happened I suspected that I made some mistake into code because window was completely blank. After that I started to move cursor and mouse wheel and... my image (4000,3000px) became visible as a small thumbnail. Far away behind window's borders. 

Also, when you manipulate with picturebox content without moving of mouse whell and without dragging, image continues to change its starting positions in equal offsets.

----------


## passel

Goshx,
  You did put in a fix for one known issue where the zoom was being applied as a delta to the current size, rather than as a current zoom value to the original size didn't you.
That was mentioned in the other thread that you started, and I'll quote it here. There may be other things like that.

Quote:
  I noticed while testing that sometimes when I was zoomed in and drawing near the bottom of the image, that the drawing was offset quite aways from the mouse (always in Y in my case with several different images, but don't know if that would always be the case).

I determined the reason for this is that the bounds (_ImageBounds.Width and Height) ratios had drifted.
The Width and Height values were initially different in my images, but if you zoomed way out, then zoomed way in, because of the calculation of the width and height always being in reference to themselves (and not the original image) and limited to an Int (CInt), each would round to an Int at different points and eventually the Width and Height would become square to be in phase with each other.

So, I just modified those two lines where the Width and Height of the bounds was calculated to fix that by referencing the original size of the image. The other places where you use zoomRatio for recentering are fine as I assume once the bounds are correct, other calculations will take care of themselves.


```
'In ZoomPictureBox_Main.vb
    'Calculate the image bounds for a given ZoomFactor,  
    Private Function GetZoomedBounds() As Rectangle

        'Find the zoom center relative to the image bounds.
        Dim imageCenter As Point = FindZoomCenter(_ZoomMode)

        'Calculate the new size of the the image bounds.
        _previousZoomfactor = _ImageBounds.Width / _Image.Width
        If Math.Abs(_ZoomFactor - _previousZoomfactor) > 0.001 Then
            Dim zoomRatio As Double = _ZoomFactor / _previousZoomfactor
      '   _ImageBounds.Width = CInt(_ImageBounds.Width * zoomRatio)  'Fixed these two lines so they don't accumulate Integer rounding values
      '   _ImageBounds.Height = CInt(_ImageBounds.Height * zoomRatio)
            _ImageBounds.Width = CInt(_Image.Width * _ZoomFactor)    
            _ImageBounds.Height = CInt(_Image.Height * _ZoomFactor)

            'Find the resulting position of the zoom center prior to correction.
            Dim newPRelative As Point
            newPRelative.X = CInt(imageCenter.X * zoomRatio)
            newPRelative.Y = CInt(imageCenter.Y * zoomRatio)

            'Apply a correction to return the zoom center to its previous position.
            _ImageBounds.X += imageCenter.X - newPRelative.X
            _ImageBounds.Y += imageCenter.Y - newPRelative.Y

        End If
        _previousZoomfactor = _ZoomFactor
        Return _ImageBounds
    End Function
```

----------


## Goshx

Yes, I've seen your post but didn't know that it was related with my question at that moment. 

When I changed code to your, things are a bit better now (especially when image is not large and when it is centered). Unfortunately, problem still persists.  Large zoomed images makes huge difference between original position and new one calculated from ImagePosition and ZoomFactor.

----------


## boops boops

Thanks to you both, Goshx and Passel, for identifying some problems with the ZoomPictureBox. There seem to be two different issues.

1. There is indeed something wrong with the "save view / restore view" logic. If only the zoom, or only the position, changes after saving the view, the restore works correctly. But after both zoom and position have changed, the restore goes wrong. That means I need to debug what happens in and after the ZoomFactor and ImagePosition property Set clauses.

2. A certain amount of imprecision happens due to the large zoom range. When zoomed right out (as an extreme example, a 2000 pixel wide image displayed at 10 pixels wide i.e. ZoomFactor 0.05) it's not surprising that it's difficult to use the mouse precisely. A microbe passing wind near your mouse could cause a jump of 50 image pixels, so to speak :Smilie: . When you zoom right in (magnification > * 4 for example) the "pixels" tend to jiggle about due to the way GDI+ renders highly magnified images. But I don't see why this should result in a persistent shift. The corrections in the post above, although "cleaner code", above don't seem to make any visible difference here. I wonder if it's just a matter of rounding errors? I'll try replacing rectangles and points by RectangleFs and PointFs wherever possible, to see if it helps.

BB

----------


## Goshx

an experienced VS programmer would find "the heck" without many problems, I think  :Smilie:

----------


## boops boops

> an experienced VS programmer would find "the heck" without many problems, I think


Well I don't even know what "the heck" is let alone how to find it! Never mind, I think I've got a handle on both problems.

re: 1
As long as you restore first the Zoom then the ImagePosition, save/restore seems to work fine. That's no doubt because setting ZoomFactor changes the ImagePosition, but not vice versa. I'll have to think how to build that into the control in some idiot-proof way.

re: 2
It is indeed a matter of Integer/Single rounding errors. I've replaced all the appropriate Rectangles, Points and CInts by RectangleFs, PointFs and CSngs. Now everything seems to zoom smoothly, or at least drift by no more than 1 pixel per full-range zoom. I must assume that anything more that that is either microbial flatulence or user tremor.

For those interested, there's a zip of my present (interim) version of the ZPB and TestForm attached. But I'll post a proper update soon. 

BB

----------


## Goshx

It is really funny and almost unbelievable that changing order of ImagePosition and ZoomFactor solves the problem. I could bet on 1 million that it is impossible  :Smilie: 

That means, you have to isolate/keep ZoomFactor value before calculating of ImagePosition. In any case, this problem has been solved. Thank you.

----------


## boops boops

I'm glad it works for you too. You can never be sure :LOL: . 

I'm thinking of dealing with it by adding public SaveView and RestoreView methods to the next version. An alternative I first had in mind was to expose the ImageBounds property as Read/Write instead of ReadOnly. The problem with that is what to do if the user specifies a rectangle with a different aspect ratio to the image. I don't want to throw exceptions from the control if I can avoid it. Something that occurred to me was to stretch the image in one direction only to fit the specified rectangle. But it isn't the job of the ZoomPictureBox to do things like that: it's an image viewing control, not an image editor.

BB

----------


## Reverend Jim

I took your excellent ZoomPictureBox control and made a slight change that you may want to include. I added a "Constrain" property to enable/disable dragging of the image outside of the displayable area. Your control saved me a (rude word)-ton of work. Thanks.

    <Category("_ZoomPictureBox"),
        Description("Constrain image to within visible area")>
    Public Property Constrain As Boolean
        Get
            Return _Constrain
        End Get
        Set(value As Boolean)
            _Constrain = value
        End Set
    End Property

    Private _Constrain As Boolean

    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)

        If _dragging Then

            Me.Invalidate(_ImageBounds)

            'calculate new image position

            Dim newx As Integer = _ImageBounds.X + e.X - _startDrag.X
            Dim newy As Integer = _ImageBounds.Y + e.Y - _startDrag.Y

            'adjust if Constrain=True to keep as much ofg image as possible in view

            If _Constrain Then

                Select Case True

                    'Image will fit in view - shift left or right to avoid clipping
                    Case _ImageBounds.Width <= Me.Width
                        If newx < 0 Then newx = 0
                        If newx + _ImageBounds.Width > Me.Width Then newx = Me.Width - _ImageBounds.Width

                    'shift left to remove vertical null space
                    Case newx > 0
                        newx = 0

                    'shift right to remove vertical null space
                    Case newx + _ImageBounds.Width < Me.Width
                        newx = Me.Width - _ImageBounds.Width

                End Select

                Select Case True

                    'Image will fit in view - shift up or down to avoid clipping
                    Case _ImageBounds.Height <= Me.Height
                        If newy < 0 Then newy = 0
                        If newy + _ImageBounds.Height > Me.Height Then newy = Me.Height - _ImageBounds.Height

                    'shift up to remove horizontal null space
                    Case newy > 0
                        newy = 0

                    'shift down to remove horizontal null space
                    Case newy + _ImageBounds.Height < Me.Height
                        newy = Me.Height - _ImageBounds.Height

                End Select

            End If

            _ImageBounds.X = newx
            _ImageBounds.Y = newy
            _startDrag = e.Location

            Me.Invalidate(_ImageBounds)

        End If

        MyBase.OnMouseMove(e)

    End Sub

----------


## boops boops

Hi Rev. Jim, my apologies for not noticing your suggestion before. Yikes, it's been nearly 6 months! Somehow I got unsubscribed from this thread so I didn't get notified. 

Now I have made some improvements to the ZoomPictureBox. Among other things it includes a way to prevent the image getting dragged out of view. The method is much the same as Rev. Jim's, but it deals with more situations (dragging, zooming and control size changed). There is a new *DragMargin* property that sets the minimum width that always stays visible. 

The main change deals with some performance problems that affected the previous version. With *large images* (say more than 8 MPixels, depending on hardware), image dragging was jerky and slow when zoomed-in, and zooming could be very slow when zoomed-out. The new version works smoothly with much larger images, for example 30 MPixels. It even works reasonably well for a 200 MPixel image although I don't intend to try it with anything bigger!

Here's how it works. When you set the Image property, it generates a List of images each reduced by one quarter of the preceding pixel size until a minimum width or height of 128 pixels is reached. The OnPaint sub selects a suitable low-resolution image from the List and paints it immediately; this is much quicker than painting the full-res image. At the same time a System.Timers.Timer is triggered. Once the timer interval elapses, the image is replaced by the full-resolution version. 

The attachments below are a zip file with the revised ZoomPictureBox code (two files, ZoomPictureBox_Main.vb and ZoomPictureBox_Public Properties.vb), and another zip file with code for a test form (TestForm.vb). There's no need to add a ZoomPictureBox to the test form in the designer, it's added in code. The form code allows you to double-click the ZoomPictureBox at runtime to select the image. 

BB

----------


## Reverend Jim

No problem. Thanks for the update. I can't wait to check it out.

----------


## Reverend Jim

I'm having several problems with the new code under Visual Studio 2017.

I load up the previous project from ZoomPictureBox+TestForm+Demo.zip and let VS2017 do the conversion.

I run the previous code after the rebuild to make sure it works (it does).

I replace the previous versions of ZoomPictureBox_Main.vb, ZoomPictureBox_Public Properties.vb and TestForm.vb with their newer version.

I try a rebuild and get a pile of errors





Could you please zip the current version as a complete VS project and post it?

----------


## Reverend Jim

I'm having several problems with the new code under Visual Studio 2017.

I load up the previous project from ZoomPictureBox+TestForm+Demo.zip and let VS2017 do the conversion.

I run the previous code after the rebuild to make sure it works (it does).

I replace the previous versions of ZoomPictureBox_Main.vb, ZoomPictureBox_Public Properties.vb and TestForm.vb with their newer version.

I try a rebuild and get a pile of errors



Could you please zip the current version as a complete VS project and post it?

----------


## boops boops

Apologies for the long delay. I didn't include a designer file in the TestForm.vb.zip in post #75, but you can get by without it by copying the code into an existing form.

The following steps work for me in VS2017:
1. Download the zip files from post #75 to a convenient folder and unzip them. 
2. In Visual Studio 2017, start a new WinForms project. Leave Form1 and everything else unchanged.
3. Click *Add Existing Item* in the VS Project menu and select the three unzipped files (e.g. with Shift-select). Ignore any errors for the moment.
4. Select the code from TestForm.vb (excluding Class and End Class statements) and Cut it using Ctrl-x. Paste it into the default form (Form1). The errors should disappear.
5. Run the project. 

The test form code enables you to Double-click the ZoomPictureBox to load an image, and change the form size to resize the ZoomPictureBox. 

It's not hard to zoom and pan very large images (e.g. 50 megapixel) in this version. It even worked on my hardware with a 250 megapixel image, although the zooming was no longer smooth. By the way, I download large images for testing purposes from Wikipedia's _Picture of the Day_.

BB

----------


## pgscannell1948

First of all, thank you for making this available to us in the development community.  Your product has been a tremendous addition to my application.

Is there a way to remove the image from the picture box when we are finished viewing/zooming it?  I have a dilemma where I can't delete the image file that has been "Zoom Pictured" after I finish and close the popup window that has it on it.

Regular PictureBox controls have an .Image property that can be set to Nothing as well as an .Invalidate() method.  I can't seem to find those things in your user control.  I need a way to be able to delete the image from within my application if the user wishes to do so.  However, if I have run the Zoom Picture Box on an image, I can't do that.  I get the runtime error that the object is currently in use.

Thanks in advance,
Paul

----------


## boops boops

Hi Paul, welcome to VBForums. 

The ZoomPictureBox allows you to set the Image to Nothing and to call its Invalidate method in much the same way as a PictureBox. In both cases, the image source file remains locked. The safest way to avoid this is to read the image as a Stream instead of opening it with Image.FromFile(_filename)_ or New Bitmap(_filename_).


```
    Using stream As IO.Stream = IO.File.OpenRead(filename)
         ZoomPictureBoxName.Image = Image.FromStream(stream)
      End Using
```

The source file is closed at the end of the Using block, so you are free to delete it independently of the image.

BB

----------


## davidgarnett

I would like to contact the author of this library.  I'm using the library in an application and need some information that I hope he can provide

----------


## .paul.

> I would like to contact the author of this library.  I'm using the library in an application and need some information that I hope he can provide


BoopsBoops is the author of this software. This thread is the place to ask your questions

----------


## davidgarnett

> BoopsBoops is the author of this software. This thread is the place to ask your questions


Paul,

Thank you for your reply ... I'm new to VBForums.  I thought I replied with my question to this thread.  

If I didn't, please let me know how to reply.

----------


## .paul.

> Paul,
> 
> Thank you for your reply ... I'm new to VBForums.  I thought I replied with my question to this thread.  
> 
> If I didn't, please let me know how to reply.


Yeah you're posting in the right place, but you haven't given any details with your comment. Boops Boops will need to know what it is you need to know....

----------


## davidgarnett

> Yeah you're posting in the right place, but you haven't given any details with your comment. Boops Boops will need to know what it is you need to know....


There is no license information for ZPLib that I can find.  *Can the developer associate a license with the library? ... perhaps MIT?*

----------


## boops boops

> There is no license information for ZPLib that I can find.  *Can the developer associate a license with the library? ... perhaps MIT?*


That question applies to any code library, not just ZPLib. And it's not something I know much about. Please address your question to another forum such as Visual Basic .Net or C#. 

BB

----------


## Delaney

Boops Boops, I think Davidgarnett want to know what is the license associated with your library/class to know if he can use it freely or not in his own applications.

----------


## boops boops

As far as I know all code posted in the CodeBank is unlicensed, so you are free use it however you like. if you include the code in a licensed project, it would be polite to add a comment referring to this thread or to my authorship. BB

----------


## john_g33

Hello, thank you for providing such great code.
Unfortunately, the main post directs to post #75 to get the February 2019 version, but post #75 redirects back to the main post, which are two zip files, *both from 2012*, none of them with the newly added "DragMargin" property. There may have been a mix-up when editing posts. Would it be possible for OP to upload the new version? Thanks a lot.

----------


## boops boops

Hi John, you are right. When I posted the last link nearly 3 years ago, I intended move it to post #1 where anyone could find it. But I discovered some errors and never got around to fixing them. Life got in the way... :Blush:  And then a month ago - even worse - I decided to clear out what seemed to be obsolete links in the thread. I forgot that the link in post #1 wasn't updated. What a mess: it took me quite a while to sort it out but now at least I have a new version with the following changes:

1. SafeMargin works OK. 
2. The two separate files for the ZoomPictureBox class (Main and Properties) are now merged into one. Separating them seemed like a good idea at first but no longer.
3. The panning and zooming for very large images works smoothly, but they can be very slow to load. There must be a better way. And very large images seem prone to throw OutOfMemory exceptions in Visual Studio 2022. That will take some work
4. There was a problem with transparent backgrounds. I don't know if anyone noticed but it's fixed now.

Here's an interim version of the ZoomPictureBox Class you may care try out:
ZoomPictureBox_Jan2022.vb
Questions, suggestions and criticism are welcome.

BB

----------

