我正在开发一个程序,可以在图片框中显示尼康相机的实时图像。我希望能够将光标悬停在图像上,并在另一个图片框中显示光标周围的放大区域。我还想添加十字准线而不是鼠标指针。到目前为止我找到的唯一解决方案如下:
它完全符合我的要求,但我无法让它工作。更具体地说,picZoom 中没有显示任何内容。在示例中,加载图像,而在我的例子中,显示视频流。这可能就是我无法让它发挥作用的原因。我对 C# 比较陌生,并没有完全理解这个例子。
假设我有 picBox,可以在其中接收视频流。如何在 picZoom 中用十字准线显示光标周围 picBox 的一部分(假设尺寸为 x,y 的光标周围的矩形),如示例中所示。我不需要担心 picBox 和 picZoom 的不同尺寸,因为它们不会变化。我还希望能够通过因子 ZoomFactor 来改变缩放程度。
如果有人能给我指点或解决方案,我将不胜感激。另外,如果我的问题格式不正确,抱歉,我是论坛新手。
谢谢!
亚历山大
我会这样处理
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% 确定您想要什么十字准线,但这使用内置的十字准线光标。
通过一些调整,您可以将 @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);
}
}