Click here to Skip to main content
15,914,419 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am new to C# programming.I am working with windows application, I have picture Box to load image from the directory. I am trying to get some idea how can I display magnified image of particular area depending on the cursor coordinates. Like if the cursor hover on the particular field on the picture it should zoom that area.

Rectangle R = new Rectangle(0, 0, 60000, 480);
Pen cpen = new Pen(Color.Black, 3);
Point mouseDownLoc;
public Form()
{
InitializeComponent();
//Rectangle screen = Screen.PrimaryScreen.WorkingArea;
//int w = Width >= screen.Width ? screen.Width : (screen.Width + Width) / 2;
//int h = Height >= screen.Height ? screen.Height : (screen.Height + Height) / 2;
//this.Location = new Point((screen.Width - w) / 2, (screen.Height - h) / 2);
//this.Size = new Size(w, h);
this.pictureBox2.MouseEnter += (sender, args) => this.pictureBox1.Show();
this.pictureBox2.MouseLeave += (sender, args) => this.pictureBox1.Hide();
this.pictureBox2.MouseMove += (sender, args) => DoMagnification();
}
private void DoMagnification()
{
try
{
//clean up after our last run
var oldImage = this.pictureBox1.BackgroundImage;
if (oldImage != null)
oldImage.Dispose();

var position = this.pictureBox2.PointToClient(Cursor.Position);
var pboxWidth = this.pictureBox1.Width / 2;
var pboxHeight = this.pictureBox1.Height / 2;

Bitmap image = new Bitmap(this.pictureBox2.Width, this.pictureBox2.Height);
// this.pictureBox2.DrawToBitmap(image, this.pictureBox2.Bounds);

// ensure we dont go out of bounds
Rectangle cloneRect = new Rectangle(Math.Max(position.X, 0), Math.Max(position.Y, 0), pboxWidth, pboxHeight);

if (cloneRect.Width + cloneRect.X > image.Width)
cloneRect.X -= (image.Width - cloneRect.Width);

if (cloneRect.Height + cloneRect.Y > image.Height)
cloneRect.Y -= (image.Height - cloneRect.Height);

System.Drawing.Imaging.PixelFormat format =
image.PixelFormat;
// Clone a portion of the Bitmap object.
Bitmap cloneBitmap = image.Clone(cloneRect, format);

// Draw the cloned portion of the Bitmap object.
using (var graphics = CreateGraphics())
graphics.DrawImage(cloneBitmap, 0, 0);
this.pictureBox1.BackgroundImage = cloneBitmap;
this.pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;

this.pictureBox1.Location = OffsetByAFewPixels(position);
}
catch (Exception ex)
{
lblerror.Text = ex.Message;
}
}
private Point OffsetByAFewPixels(Point location)
{
return new Point(location.X + 100, location.Y + 100);
}

private void pictureBox2_MouseEnter(object sender, EventArgs e)
{
// splitContainer1.Panel1.Focus();
try
{
int fx = 0;
int fy = 0;
fx = this.ClientRectangle.Left;
fy = this.ClientRectangle.Top;
Point startpoint = pictureBox1.PointToScreen(new Point(0, 0));
Graphics G = this.CreateGraphics();
Point Position = new Point(fx + pictureBox1.Left, fy + pictureBox1.Top);
Bitmap screenGrab = new Bitmap(pictureBox2.Image.Width, pictureBox2.Image.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
G = Graphics.FromImage(screenGrab);
G.CopyFromScreen(startpoint, new Point(0, 0), pictureBox1.Size, CopyPixelOperation.SourceCopy);
pictureBox1.Image = screenGrab;
pictureBox1.BringToFront();
//pictureBox1.Visible = true;
}
catch( Exception ex)
{
if (lblerror.Text == "")
{
lblerror.Text = ex.Message;
}
else
{
lblerror.Text += ex.Message;
}
}
}
private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point currentMousePos = e.Location;
int distanceX = currentMousePos.X - mouseDownLoc.X;
int distanceY = currentMousePos.Y - mouseDownLoc.Y;
int newX = pictureBox2.Location.X + distanceX;
int newY = pictureBox2.Location.Y + distanceY;
if (newX + pictureBox2.Image.Width < pictureBox2.Image.Width && pictureBox2.Image.Width + newX > pictureBox2.Width)
pictureBox2.Location = new Point(newX, pictureBox2.Location.Y);
if (newY + pictureBox2.Image.Height < pictureBox2.Image.Height && pictureBox2.Image.Height + newY > pictureBox2.Height)
pictureBox2.Location = new Point(pictureBox2.Location.X, newY);
}
try
{
Graphics G = Graphics.FromImage(pictureBox1.Image);
//Picturebox1.CreateGraphics
GraphicsPath path = new GraphicsPath();
int L = 0;
int T = 0;
L = pictureBox1.Width + (e.X * pictureBox2.Image.Width) / pictureBox2.Width;
T = pictureBox1.Height / 2 + pictureBox2.Height - (e.Y * pictureBox2.Image.Height) / pictureBox2.Height;
path.AddRectangle(R);
G.DrawPath(cpen, path);
G.SetClip(path, CombineMode.Replace);
// Clip Magnifying area to screen capture

G.DrawImage(pictureBox2.Image, pictureBox2.Width - 2*L, T- pictureBox2.Height, pictureBox2.Image.Width +L, pictureBox2.Image.Height);
pictureBox1.Refresh();
}

catch( Exception ex)
{
if (lblerror.Text == "")
{
lblerror.Text = ex.Message;
}
else
{
lblerror.Text += ex.Message;
}
}
}
private void pictureBox2_MouseLeave(object sender, EventArgs e)
{
pictureBox1.Visible = false;
this.Refresh();
//restore views when leaving area
}
private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mouseDownLoc = e.Location;

}
}

What I have tried:

I have tried it with another picture box that is fixed to zoom on mosue enter, but I am looking for movable magnifier
Posted
Updated 4-Mar-16 6:33am
v2

You could easily make the static picturebox, that you are already using for magnification, dynamically show/hide/move based on user input. Such as onMouseEnter it could move to the desired location (based on the mouse), onMouseMove it would follow the mouse, and onMouseLeave it would hide.

Just handle those events for the parent picturebox, and it should work great. Just be sure to offset the Magnified picturebox from the cursor a pixel or two. If you make the magnified picturebox show under the cursor, you will get into a loop because the onMouseLeave event will fire on the parent picturebox when the magnified one shows underneath, which would cause the magnified picturebox to disappear, which would trigger onMouseEnter and show it again....

Here is a quick and dirty sample (hint: dont go near the edges of the form)

Just create a form with a picturebox (pictureBox1) that has DockStyle=Full, and another smaller picturebox with Visible=false. Then give pictureBox1 a Background image.

C#
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.pictureBox1.MouseEnter += (sender, args) => this.pictureBox2.Show();

            this.pictureBox1.MouseLeave += (sender, args) => this.pictureBox2.Hide();

            this.pictureBox1.MouseMove += (sender, args) => DoMagnification();
        }

        private void DoMagnification()
        {
            // clean up after our last run
            var oldImage = this.pictureBox2.BackgroundImage;
            if (oldImage != null)
                oldImage.Dispose();

            var position = this.pictureBox1.PointToClient(Cursor.Position);
            var pboxWidth = this.pictureBox2.Width / 2;
            var pboxHeight = this.pictureBox2.Height / 2;

            Bitmap image = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height);
            this.pictureBox1.DrawToBitmap(image, this.pictureBox1.Bounds);

            // ensure we dont go out of bounds
            Rectangle cloneRect = new Rectangle(Math.Max(position.X, 0), Math.Max(position.Y, 0), pboxWidth, pboxHeight);

            if (cloneRect.Width + cloneRect.X > image.Width)
                cloneRect.X -= (image.Width - cloneRect.Width);

            if (cloneRect.Height + cloneRect.Y > image.Height)
                cloneRect.Y -= (image.Height - cloneRect.Height);

            System.Drawing.Imaging.PixelFormat format =
                image.PixelFormat;
            // Clone a portion of the Bitmap object.
            Bitmap cloneBitmap = image.Clone(cloneRect, format);

            // Draw the cloned portion of the Bitmap object.
            using (var graphics = CreateGraphics())
                graphics.DrawImage(cloneBitmap, 0, 0);
            this.pictureBox2.BackgroundImage = cloneBitmap;
            this.pictureBox2.BackgroundImageLayout = ImageLayout.Zoom;

            this.pictureBox2.Location = OffsetByAFewPixels(position);
        }

        private Point OffsetByAFewPixels(Point location)
        {
            return new Point(location.X + 1, location.Y + 1);
        }
    }
 
Share this answer
 
v4
Comments
Member 12076824 4-Mar-16 11:15am    
Thanks for response. I appreciate your help. I am running into problem as it throws error parameter is not valid when I try to magnify area around rightmost corner of the image(Maybe if I can get way to display that part of the image on left rather than on right side) and magnified image disappears when scrolled down to rest of the image in picturebox. I am using split container to display picture box in one area and data fields in another area.

Rectangle R = new Rectangle(0, 0, 60000, 480);
Pen cpen = new Pen(Color.Black, 3);
Point mouseDownLoc;
public Form()
{
InitializeComponent();
//Rectangle screen = Screen.PrimaryScreen.WorkingArea;
//int w = Width >= screen.Width ? screen.Width : (screen.Width + Width) / 2;
//int h = Height >= screen.Height ? screen.Height : (screen.Height + Height) / 2;
//this.Location = new Point((screen.Width - w) / 2, (screen.Height - h) / 2);
//this.Size = new Size(w, h);
this.pictureBox2.MouseEnter += (sender, args) => this.pictureBox1.Show();
this.pictureBox2.MouseLeave += (sender, args) => this.pictureBox1.Hide();
this.pictureBox2.MouseMove += (sender, args) => DoMagnification();
}
private void DoMagnification()
{
try
{
//clean up after our last run
var oldImage = this.pictureBox1.BackgroundImage;
if (oldImage != null)
oldImage.Dispose();

var position = this.pictureBox2.PointToClient(Cursor.Position);
var pboxWidth = this.pictureBox1.Width / 2;
var pboxHeight = this.pictureBox1.Height / 2;

Bitmap image = new Bitmap(this.pictureBox2.Width, this.pictureBox2.Height);
// this.pictureBox2.DrawToBitmap(image, this.pictureBox2.Bounds);

// ensure we dont go out of bounds
Rectangle cloneRect = new Rectangle(Math.Max(position.X, 0), Math.Max(position.Y, 0), pboxWidth, pboxHeight);

if (cloneRect.Width + cloneRect.X > image.Width)
cloneRect.X -= (image.Width - cloneRect.Width);

if (cloneRect.Height + cloneRect.Y > image.Height)
cloneRect.Y -= (image.Height - cloneRect.Height);

System.Drawing.Imaging.PixelFormat format =
image.PixelFormat;
// Clone a portion of the Bitmap object.
Bitmap cloneBitmap = image.Clone(cloneRect, format);

// Draw the cloned portion of the Bitmap object.
using (var graphics = CreateGraphics())
graphics.DrawImage(cloneBitmap, 0, 0);
this.pictureBox1.BackgroundImage = cloneBitmap;
this.pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;

this.pictureBox1.Location = OffsetByAFewPixels(position);
}
catch (Exception ex)
{
lblerror.Text = ex.Message;
}
}
private Point OffsetByAFewPixels(Point location)
{
return new Point(location.X + 100, location.Y + 100);
}

private void pictureBox2_MouseEnter(object sender, EventArgs e)
{
// splitContainer1.Panel1.Focus();
try
{
int fx = 0;
int fy = 0;
fx = this.ClientRectangle.Left;
fy = this.ClientRectangle.Top;
Point startpoint = pictureBox1.PointToScreen(new Point(0, 0));
Graphics G = this.CreateGraphics();
Point Position = new Point(fx + pictureBox1.Left, fy + pictureBox1.Top);
Bitmap screenGrab = new Bitmap(pictureBox2.Image.Width, pictureBox2.Image.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
G = Graphics.FromImage(screenGrab);
G.CopyF
Yea it is giving those errors because the bounds of the magnified image is outside the bounds of the original (why I mentioned avoiding corners earlier :)). You will have to add a little bit of code to prevent that. That code would go something like:

C#
Graphics G = this.CreateGraphics();

// Ensure we do not cross the left boundary
int gx = Math.Max(fx + pictureBox1.Left, 0);

// Ensure we do not cross the right boundary
gx = Math.Min(fx, pictureBox2.Width - pictureBox1.Width);

// Ensure we do not cross the top boundary
int gy = Math.Max(fy + pictureBox1.Top, 0);

// Ensure we do not cross the bottom boundary
gy = Math.Min(gy, pictureBox2.Height - pictureBox1.Height);

Point Position = new Point(gx, gy);


Now I haven't run this, so you may have to do some debugging, but the idea is to ensure that the bounds you use to extract the 'Magnified' image are always within the bounds of the original. If you go outside the bounds of the original, you will see InvalidParameterException, OutOfMemoryException, BadImageFormatException (why this one pops up, I'll never understand... but it does), and maybe some others.

So you will probably have to play around with it, but it should work with minimal tweaking.
 
Share this answer
 
Comments
Member 12076824 4-Mar-16 12:42pm    
Thanks Mike. I will give it a try and see if I can make it work.
Mike Baldini 4-Mar-16 12:51pm    
No problem at all. I did something similar 5-6 years ago for an embedded google maps image inside the accounting software I was working on. I don't get to do much (any) winforms anymore, it was nice to get my head out of FibreChannel switch drivers for a bit. :)

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900