通过将光标悬停在另一个图片框中显示放大的部分图片框c#

问题描述 投票:0回答:2

我正在开发一个程序,可以在图片框中显示尼康相机的实时图像。我希望能够将光标悬停在图像上,并在另一个图片框中显示光标周围的放大区域。我还想添加十字准线而不是鼠标指针。到目前为止我找到的唯一解决方案如下:

缩放光标后第二个图片框中的图像

它完全符合我的要求,但我无法让它工作。更具体地说,picZoom 中没有显示任何内容。在示例中,加载图像,而在我的例子中,显示视频流。这可能就是我无法让它发挥作用的原因。我对 C# 比较陌生,并没有完全理解这个例子。

假设我有 picBox,可以在其中接收视频流。如何在 picZoom 中用十字准线显示光标周围 picBox 的一部分(假设尺寸为 x,y 的光标周围的矩形),如示例中所示。我不需要担心 picBox 和 picZoom 的不同尺寸,因为它们不会变化。我还希望能够通过因子 ZoomFactor 来改变缩放程度。

如果有人能给我指点或解决方案,我将不胜感激。另外,如果我的问题格式不正确,抱歉,我是论坛新手。

谢谢!

亚历山大

c# image picturebox
2个回答
1
投票

我会这样处理

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);
            }
        }
    }
}

要连接它,您所需要做的就是在表单中添加一个

Magnifier
,为其指定大小,然后将其
Source
设置为您希望其放大的
PictureBox

   this.magnifier1.Source = this.pictureBox1;

我使用了这个答案中的方法来忽略来自放大镜窗口的消息。

重要的是,我只为源 PictureBox 的

PictureBoxSizeMode.Normal
SizeMode 编写了缩放数学。 但我认为这是一个很好的开始。

不能 100% 确定您想要什么十字准线,但这使用内置的十字准线光标。


0
投票

通过一些调整,您可以将 @Wyck 的代码与 PictureBoxSizeMode.StretchImage 一起使用

protected override void OnPaint(PaintEventArgs pe)
    {
        if (!DesignMode && Source != null && Source.Image != null)
        {
            Rectangle destRect = new (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:
            float stretch_X = source.Image.Width  / (float)source.Width;
            float stretch_Y = source.Image.Height / (float)source.Height;
            Rectangle srcRect = new ((int)(sourcePoint.X * stretch_X) - Width / 4, (int)(sourcePoint.Y * stretch_Y) - Height / 4, Width / 2, Height / 2);
            pe.Graphics.DrawImage(source.Image, destRect, srcRect, GraphicsUnit.Pixel);
        }
        else
        {
            base.OnPaint(pe);
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.