0

I am working on a program that displays the liveView image from a Nikon camera in a pictureBox. I want to be able to hover with the cursor over the image and display a zoomed in area around the cursor in another picturebox. I would also like to add a crosshair instead of mouse pointer. The only solution I have found so far is the following:

zoom an image in a second picturebox following cursor

It does exactly what I want, however I can not get it to work. More specifically, nothing is showing up in picZoom. In the example, images are loaded while in my case, a video stream is shown. That might be the reason why I am not getting it to work. I am relatively new to c#, and did not fully understand the example.

Lets say I have picBox where I receive the video stream. How do I show a portion of picBox around the cursor (let's say a rectangle around the cursor of dimensions x,y) in picZoom with a crosshair as in the example. I do not need to worry about differing dimensions of picBox and picZoom since they will not vary. I also want to be able to vary the degree of zoom by a factor zoomFactor.

If anyone could give me pointers or a solution, it would be greatly appreciated. Also, sorry if my question is poorly formatted, I am new to the forum.

Thank you!

Alexander

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794

1 Answers1

0

I would approach it like this

using System;
using System.Drawing;
using System.Windows.Forms;

namespace MagnifierExample
{
    class Magnifier : PictureBox
    {
        public Magnifier()
        {
            Visible = false;
        }

        PictureBox source;
        private Point sourcePoint;
        Cursor oldCursor;

        public PictureBox Source
        {
            get
            {
                return source;
            }
            set
            {
                if (source != null)
                {
                    source.MouseEnter -= Source_MouseEnter;
                    source.MouseLeave -= Source_MouseLeave;
                    source.MouseMove -= Source_MouseMove;
                    source.Cursor = oldCursor;
                }
                source = value;
                if (source != null)
                {
                    source.MouseEnter += Source_MouseEnter;
                    source.MouseLeave += Source_MouseLeave;
                    source.MouseMove += Source_MouseMove;
                    oldCursor = source.Cursor;
                    source.Cursor = Cursors.Cross;
                }
            }
        }

        private void Source_MouseEnter(object sender, EventArgs e)
        {
            Visible = true;
            BringToFront();
        }

        private void Source_MouseLeave(object sender, EventArgs e)
        {
            Visible = false;
        }

        private void Source_MouseMove(object sender, MouseEventArgs e)
        {
            sourcePoint = e.Location;
            Location = new Point(source.Location.X + e.X - Width / 2, source.Location.Y + e.Y - Height / 2);
            Invalidate();
        }

        protected override void WndProc(ref Message m)
        {
            const int WM_NCHITTEST = 0x0084;
            const int HTTRANSPARENT = (-1);

            if (!DesignMode && m.Msg == WM_NCHITTEST)
            {
                m.Result = (IntPtr)HTTRANSPARENT;
            }
            else
            {
                base.WndProc(ref m);
            }
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            if (!DesignMode && Source != null && Source.Image != null)
            {
                Rectangle destRect = new Rectangle(0, 0, Width, Height);
                // IMPORTANT: This calculation will depend on the SizeMode of the source and the amount you want to zoom.
                // This does 2x zoom and works with PictureBoxSizeMode.Normal:
                Rectangle srcRect = new Rectangle(sourcePoint.X - Width / 4, sourcePoint.Y - Height / 4, Width / 2, Height / 2);
                pe.Graphics.DrawImage(Source.Image, destRect, srcRect, GraphicsUnit.Pixel);
            }
            else
            {
                base.OnPaint(pe);
            }
        }
    }
}

To hook it up all you have to do is add a Magnifier to your form, give it a size, and set its Source to the PictureBox you want it to magnify.

   this.magnifier1.Source = this.pictureBox1;

I used the approach in this answer to ignore messages from the magnifier window.

Importantly, I only coded up the zoom math for the PictureBoxSizeMode.Normal SizeMode of the source PictureBox. But I think this is a pretty good start.

Not 100% sure what you wanted for crosshairs, but this uses the built-in crosshair cursor.

Wyck
  • 10,311
  • 6
  • 39
  • 60
  • @AlexanderEngman What I have provided here is a Magnifer control. If you add this code as a Magnifer.cs file in your project, and build it, then, using the form designer, you can drag a Magnifier component from your toolbox into your form. Then, in the InitializeComponent method of the code for your form, you can add that one-liner where you connect this Magnifier control to the picture box you want to enable magnification for. – Wyck Mar 03 '22 at 16:31
  • I tried your suggestiong, and it worked! Thank you so much! Not only did I learn how to magnify a picturebox, I also learned how to add files and tools to my project. The only issue I am having is that while this is in general doing what I want, what I would really like is for the magnifier to be stationary (like a pictureBox) and whatever area (of size x,y) surrounds the cursor should be displayed in it. Right now, the magnifier tracks the cursor. Do you have any solutions to this? Again, thank you so much! You have already helped tremendously! – AlexanderEngman Mar 03 '22 at 17:00
  • I guess your specification of _...display a zoomed in area around the cursor_ was a little ambiguous, eh? If you want the magnifier window be stationary then you could remove the line that starts with `Location = new Point(` and just position the magnifier control manually on your form wherever you want it using the form designer. You'll probably also want to get rid of all the lines where I set `Visible = true` or `Visible = false`. And you won't need the `BringToFront` line either. – Wyck Mar 03 '22 at 17:05
  • Yes you are correct, my initial statement was rather unclear. Will try to be more precise in the future. Anyway, thanks again for your help! – AlexanderEngman Mar 03 '22 at 17:23