Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / multimedia / GDI+

A Beautiful Magnifying Glass Effect of Image in WinForm

4.31/5 (9 votes)
12 Jan 2017CPOL1 min read 20.6K   2.3K  
Use common panel and GDI+ to achieve a magnifier effect of image in winform.

 

Introduction

In some cases, image magnification is very useful. But to achieve a beautiful magnification effect is't easy, especially in winform using C#. Now I do it, although it may not be perfect. I hope you can like it,

Background

I have been working on image acquisition using industrial cameras, and there are many pictures to browse for user.

And is to see the details of the image. I try to use WinForm to facilitate the users for this purpose.

Simple principle

Create two custom controls, one to display full image, and one to display partial enlarged image.

Using Gdi to achieve a circular control.

C#
private void PartialMagPicPanel_Load(object sender, EventArgs e)
        {
            IntPtr dc;
            IntPtr region;
            IntPtr hpen2;
            IntPtr holdpen;
            dc = GetDC(this.Handle);
            BeginPath(dc);
            hpen2 = CreatePen(5, 5, ColorTranslator.ToWin32(Color.Red));
            holdpen = (IntPtr)SelectObject(dc, hpen2);
            Ellipse(dc, 0, 0, this.Width, this.Height);
            DeleteObject(hpen2);
            EndPath(dc);
            region = PathToRegion(dc);
            SetWindowRgn(this.Handle, region, true);
        }

        [System.Runtime.InteropServices.DllImport("gdi32")]
        private static extern IntPtr BeginPath(IntPtr hdc);

        [System.Runtime.InteropServices.DllImport("gdi32")]
        private static extern int SetBkMode(IntPtr hdc,int nBkMode);
        const int TRANSPARENT = 1;

...

When the mouse is int the enlarged image panel, the control follows the mouse position. And converts the current mouse positon to original image. Set the magnification area size in advance, Calculates the position of the new region in original image.

Daw the new area onto the enlarged iamge panel.

Using the code

A

Create the enlarged image panel in full image panel.
C#
public partial class PicDataPanel : UserControl
    {
        private PartialMagPicPanel partailMagImageView = null;

        public PartialMagPicPanel PartailMagImageView
        {
            get { return partailMagImageView; }
            set { partailMagImageView = value; }
        }
        public PicDataPanel()
        {
            InitializeComponent();
            partailMagImageView = new PartialMagPicPanel();
            partailMagImageView.Location = new Point(2, 2);
            partailMagImageView.Size = new Size(this.Width / 2, this.Width / 2);
            partailMagImageView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.Controls.Add(partailMagImageView);
        }
    }

B

Create method of events for both panel controls.

C#
...

        private System.Windows.Forms.PaintEventHandler Full_Paint_Handler = null;
        private System.Windows.Forms.PaintEventHandler PartialMag_Paint_Handler = null;
        private System.Windows.Forms.MouseEventHandler PartialMag_MouseMove_Handler = null;
        private System.Windows.Forms.MouseEventHandler PartialMag_MouseWheel_Handler = null

        private void Full_Paint(object sender, PaintEventArgs e)
        {
            ...

        private void PartialMag_Paint(object sender, PaintEventArgs e)
        {
            ...
        }

        private void PartialMag_MouseMove(object sender, MouseEventArgs e)
        {
            ...
        }

        private void PartialMag_MouseWheel(object sender, MouseEventArgs e)
        {
            ...
        }

...

B1

Full_Paint Method is draw the full image onto full image panel.

C#
private void Full_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(orignalimh
                , new Rectangle(0, 0, pdp.Width, pdp .Height)
                , new Rectangle(0, 0, orignalimh.Width, orignalimh.Height), GraphicsUnit.Pixel);
        }

B2

PartialMag_Paint Method is draw the enlarged image onto enalged panel. There are three part.

Part 1: Mouse point in full image panel to original image position.

C#
int srcx = (pdp.PartailMagImageView.Location.X + pdp.PartailMagImageView.Width / 2)
     * orignalimh.Width / pdp.Width;
 int srcy = (pdp.PartailMagImageView.Location.Y + pdp.PartailMagImageView.Height / 2)
     * orignalimh.Height / pdp.Height;

 Part 2: Draw enlarged image onto panel.

C#
e.Graphics.DrawImage(orignalimh
                , new Rectangle(0, 0, pdp.PartailMagImageView.Width, pdp.PartailMagImageView.Height)
                , new Rectangle(srcx - ZoomOutRate / 2, srcy - ZoomOutRate / 2, ZoomOutRate, ZoomOutRate)
                , GraphicsUnit.Pixel);

Part 3: Draw the edges of magnifier.

C#
Pen mypen = new Pen(Color.CornflowerBlue, 7);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
e.Graphics.DrawEllipse(mypen, 0, 0, pdp.PartailMagImageView.Width-7, pdp.PartailMagImageView.Height-7);

B3

PartialMag_MouseMove method is let the magnifier control follow the mouse.

C#
curMoPo = e.Location;
if (curMoPo.X != pdp.PartailMagImageView.Width / 2 && curMoPo.Y != pdp.PartailMagImageView.Height / 2)
{
   int offsetx = pdp.PartailMagImageView.Width / 2 - curMoPo.X;
   int offsety = pdp.PartailMagImageView.Height / 2 - curMoPo.Y;
   pdp.PartailMagImageView.Location = new Point(
         pdp.PartailMagImageView.Location.X - offsetx,
         pdp.PartailMagImageView.Location.Y - offsety);
}
pdp.PartailMagImageView.Invalidate(false);
pdp.PartailMagImageView.Update();
pdp.Update();

B4

PartialMag_MouseWheel method is changing the zoom ratio.

C#
if (e.Delta > 0)
{
    ZoomOutRate -= 20;
}
else
{
    ZoomOutRate += 20;
}
ZoomOutRate = ZoomOutRate < 20 ? 20 : ZoomOutRate;
ZoomOutRate = ZoomOutRate > orignalimh.Width ? orignalimh.Width : ZoomOutRate;
toolStripStatusLabel_ZOOM.Text = String.Format("Zoom:{0}", ZoomOutRate);
pdp.PartailMagImageView.Invalidate(false);
pdp.PartailMagImageView.Update();
pdp.Update();

C

Create panel control and bind events.

C#
PicDataPanel pdp = null;

 Full_Paint_Handler = new PaintEventHandler(Full_Paint);
 PartialMag_Paint_Handler = new PaintEventHandler(PartialMag_Paint);
 PartialMag_MouseMove_Handler = new MouseEventHandler(PartialMag_MouseMove);
 PartialMag_MouseWheel_Handler = new MouseEventHandler(PartialMag_MouseWheel);
 pdp = new PicDataPanel();
 pdp.Dock = DockStyle.Fill;

 pdp.Paint += Full_Paint_Handler;
 pdp.PartailMagImageView.Paint += PartialMag_Paint_Handler;
 pdp.PartailMagImageView.MouseMove += PartialMag_MouseMove_Handler;
 pdp.PartailMagImageView.MouseWheel += PartialMag_MouseWheel_Handler;

 this.panel1.Controls.Add(pdp);

Points of Interest

I am confused about how to improve performance when load a large iamge.

License

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