Today’s digital cameras take pictures with much higher resolution than many computer screens. My Canon PowerShot SD800 IS camera takes pictures at 3072 x 2204 resolution.

 

One of my laptops died recently, and I noticed that local laptop retailers have machines with 1280 X 1024 resolution. I much prefer a higher resolution display, so I ordered a customizable Dell Inspiron 1525 with 1680 x 1050.

(I’ve been ordering computers from Dell for over 20 years, back in the days when it was called PC’s Limited. Why does Dell distinguish between business/government/home laptops?)

 

I was playing around with some photos using a PictureBox control, and I wanted to add a feature that would allow click/zoom using the mouse wheel to designate a point to magnify.

 

It was pretty easy to create my own class MyPictureBox which inherits from PictureBox and handles the MouseWheel and zooming.

 

Below are C# and VB versions. If I get enough requests, maybe I’ll make a Fox version (although I like this Fox version of zooming: Enable crop and zooming in on your digital photograph display form)

 

Start Visual Studio 2008 (I think these should work in VS2005)

File->New->Project->VB/C#->Windows Application.

 

View->Code, then paste the VB/C# code below, hit F5

 

Move the mouse to designate a zoom anchor point, then mouse wheel to zoom in/out

 

If you switch back to the form designer, the ToolBox has the MyPictureBox control on it, which you can drag/drop onto a form.

 

If you already have your own form that uses a PictureBox or several, you can avoid manually changing all the instances by carefully editing the Form1.Designer.vb file to replace the type with MyPictureBox (make a backup first).

 

As an exercise, try extending this feature by adding the ability to change the anchor point while zoomed or pan the zoomed picture.

 

Some VB/C# coding issues:

·         semicolons

·         capitalization

·         intermediate arithmetic rounding results

·         event handling

 

See also:

Enable crop and zooming in on your digital photograph display form

Create your own media browser: Display your pictures, music, movies in a XAML tooltip

 

<VB Code>

 

Public Class Form1

 

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

        Me.Left = 0

        Me.Top = 0

        Me.Size = My.Computer.Screen.WorkingArea.Size

        Dim oPict = New MyPictureBox

        oPict.Size = Me.Size

        oPict.SizeMode = PictureBoxSizeMode.StretchImage

        oPict.Image = New Bitmap("d:\kids.jpg") ' path to some picture

        Me.Controls.Add(oPict)

        Me.ActiveControl = oPict

 

    End Sub

End Class

 

Public Class MyPictureBox

    Inherits PictureBox

    Private zmLevel As Integer = 1

    Private zmPt As Point

    Overloads Property Image() As Image ' we want to hook when client's set the image to reset the zoom level to unzoomed

        Get

            Return MyBase.Image

        End Get

        Set(ByVal value As Image)

            zmLevel = 1 ' reinit

            MyBase.Image = value

        End Set

    End Property

    Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)

        'MyBase.OnPaint(pe) ' don't call baseclass to paint

        If Me.Image IsNot Nothing Then

            Dim loc As Point

            Dim sz As Size

            If zmLevel <> 1 Then

                sz = New Size(Me.Image.Width / zmLevel, Me.Image.Height / zmLevel)

                ' center on zmPt

                loc = New Point(Me.Image.Width * (zmPt.X / Me.ClientRectangle.Width) - sz.Width / 2, _

                                Me.Image.Height * (zmPt.Y / Me.ClientRectangle.Height) - sz.Height / 2)  '

            Else

                loc = New Point(0, 0)   ' no zoom: we want the entire source picture

                sz = Me.Image.Size

            End If

            Dim rectSrc = New Rectangle(loc, sz)

            ' now draw the rect of the source picture in the entire client rect of MyPictureBox

            pe.Graphics.DrawImage(Me.Image, Me.ClientRectangle, rectSrc, GraphicsUnit.Pixel)

        End If

    End Sub

    Sub PictureBox_MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseWheel

        If Me.zmLevel = 1 Then  ' can only anchor when unzoomed

            Me.zmPt = New Point(e.X, e.Y)

        End If

        If e.Delta > 0 Then

            If zmLevel < 20 Then

                zmLevel += 1

            End If

        Else

            If e.Delta < 1 Then

                If zmLevel > 1 Then

                    zmLevel -= 1

                End If

            End If

        End If

        Me.Invalidate() ' queue msg to repaint

    End Sub

 

End Class

 

</VB Code>

 

 

 

 

 

<C# Code>

 

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

            this.Left = 0;

            this.Top = 0;

            this.Size = Screen.PrimaryScreen.WorkingArea.Size;

            var oPict = new MyPictureBox();

            oPict.Size = this.Size;

            oPict.SizeMode = PictureBoxSizeMode.StretchImage;

            oPict.Image = new Bitmap("d:\\kids.jpg");

            this.Controls.Add(oPict);

            this.ActiveControl = oPict;

        }

    }

}

 

public class MyPictureBox : PictureBox

{

    private int zmLevel = 1;

    private Point zmPt;

    public MyPictureBox()

    {

        this.MouseWheel += new MouseEventHandler(MyPictureBox_MouseWheel);

    }

 

    void MyPictureBox_MouseWheel(object sender, MouseEventArgs e)

    {

        if (this.zmLevel == 1)

        {

            this.zmPt = new Point(e.X, e.Y);

        }

        if (e.Delta > 0)

        {

            if (zmLevel < 20)

            {

                zmLevel += 1;

            }

        }

        else

        {

            if (e.Delta < 1)

            {

                if (zmLevel > 1)

                {

                    zmLevel -= 1;

                }

            }

        }

        this.Invalidate();

    }

    new public Image Image // overrides

    {

        get

        {

            return base.Image;

        }

        set

        {

            zmLevel = 1;

            base.Image = value;

        }

    }

    protected override void OnPaint(PaintEventArgs pe)

    {

        //base.OnPaint(pe);

        if (this.Image != null)

        {

            Point loc;

            Size sz;

            if (zmLevel != 1)

            {

                sz = new Size(this.Image.Width / zmLevel, this.Image.Height / zmLevel);

                // center on zmPt. Casts are needed so integer divide doesn't occur (intermediate double result)

                loc = new Point((int)(this.Image.Width * (zmPt.X / (double)this.ClientRectangle.Width)) - sz.Width / 2,

                                 (int)(this.Image.Height * (zmPt.Y / (double)this.ClientRectangle.Height)) - sz.Height / 2);

            }

            else

            {

                loc = new Point(0, 0);

                sz = this.Image.Size;

            }

            Rectangle rectSrc = new Rectangle(loc, sz);

            // now draw the rect of the source picture in the entire client rect of MyPictureBox

            pe.Graphics.DrawImage(this.Image, this.ClientRectangle, rectSrc, GraphicsUnit.Pixel);

        }

    }

}

 

 

</C# Code>