c# - 如何在 C# 中缩放图片框中的某个点?

标签 c# winforms zooming picturebox

这个问题之前有人问过,但因为它不起作用,而且我缺乏声誉点(我试图在问题上发表评论,但我不能)我不得不再次问这个问题。

这是之前问的问题的链接; How to zoom at a point in picturebox

我使用了链接中显示的代码,但是当我运行它时,点或形状消失了。

这是我的代码;

public partial class Form1 : Form
{
    private Matrix transform = new Matrix();     
    private double m_dZoomscale = 1.0;    
    public static double s_dScrollValue = .1;
 }
private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.Transform = transform;
        Pen mypen = new Pen(Color.Red,5);
        Rectangle rect = new Rectangle(10, 10, 30, 30);
        e.Graphics.DrawRectangle(mypen, rect);
    }
    protected override void OnMouseWheel(MouseEventArgs mea)
    {
        pictureBox1.Focus();
        if (pictureBox1.Focused == true && mea.Delta != 0)
        {
            ZoomScroll(mea.Location, mea.Delta > 0);
        }
    }
      private void ZoomScroll(Point location, bool zoomIn)
    {
        transform.Translate(-location.X, -location.Y);
        if (zoomIn)
            transform.Scale((float)s_dScrollValue, (float)s_dScrollValue);
        else
            transform.Scale((float)-s_dScrollValue, (float)-s_dScrollValue);

        transform.Translate(location.X, location.Y);

        pictureBox1.Invalidate();
    }

最佳答案

您引用的答案不可能有效。我不知道为什么它被接受,也没有被投票。除了在过去的某个时候, 显然也对它投了赞成票。我不知道我在想什么。

无论如何,该代码有一些问题:

  1. 它使用直接传入的鼠标坐标,而不是将它们转换为PictureBox 控件的坐标系。传递给 OnMouseWheel() 方法的坐标是相对于 Form 本身的,因此仅当 PictureBox 左上角与 重合时>Form 的左上角就可以了。
  2. 更有问题的是,代码完全滥用了 Matrix.Scale() 方法,传递的值似乎是比例的 delta,而实际上Scale() 方法接受比例的因子。这有两个含义:
    • 传递负值是错误的,因为负值翻转坐标系,而不是缩小比例,并且
    • 传递增量值是错误的,因为传递的值将乘以当前缩放以获得新缩放。
  3. 还有一个问题是代码以错误的顺序应用矩阵转换,因为默认顺序是“prepend”,而不是“append”(我发现后者使用起来更自然,但我假设有一些已知的原因那些专门研究矩阵数学的人解释了为什么默认是前者)。

还有一个相对较小的问题,即使忽略上述,允许用户任意调整比例因子最终会导致超出范围的值。代码最好将规模限制在合理范围内。

这是您的代码的一个版本,经过修改以解决所有这些问题:

private Matrix transform = new Matrix();
private float m_dZoomscale = 1.0f;
public const float s_dScrollValue = 0.1f;

public Form1()
{
    InitializeComponent();
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.Transform = transform;
    Pen mypen = new Pen(Color.Red, 5);
    Rectangle rect = new Rectangle(10, 10, 30, 30);
    e.Graphics.DrawRectangle(mypen, rect);
}

protected override void OnMouseWheel(MouseEventArgs mea)
{
    pictureBox1.Focus();
    if (pictureBox1.Focused == true && mea.Delta != 0)
    {
        // Map the Form-centric mouse location to the PictureBox client coordinate system
        Point pictureBoxPoint = pictureBox1.PointToClient(this.PointToScreen(mea.Location));
        ZoomScroll(pictureBoxPoint, mea.Delta > 0);
    }
}

private void ZoomScroll(Point location, bool zoomIn)
{
    // Figure out what the new scale will be. Ensure the scale factor remains between
    // 1% and 1000%
    float newScale = Math.Min(Math.Max(m_dZoomscale + (zoomIn ? s_dScrollValue : -s_dScrollValue), 0.1f), 10);

    if (newScale != m_dZoomscale)
    {
        float adjust = newScale / m_dZoomscale;
        m_dZoomscale = newScale;

        // Translate mouse point to origin
        transform.Translate(-location.X, -location.Y, MatrixOrder.Append);

        // Scale view
        transform.Scale(adjust, adjust, MatrixOrder.Append);

        // Translate origin back to original mouse point.
        transform.Translate(location.X, location.Y, MatrixOrder.Append);

        pictureBox1.Invalidate();
    }
}

通过这段代码,你会发现无论你在调整鼠标滚轮之前把鼠标放在哪里,渲染的图像都会缩放,同时保持鼠标下的点固定在适当的位置。


注意:

我查看了 Stack Overflow 上的一些类似问题,其中有一些可能对您也有用。在我看来,有些答案使事情过于复杂,但所有答案都应该有效。见:

Zoom To Point Not Working As Expected
Zoom in on a fixed point using matrices
Zooming graphics without scrolling

关于c# - 如何在 C# 中缩放图片框中的某个点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44566229/

相关文章:

c# - C#如何使用操作系统的复制粘贴功能

c# - 为什么 DevExpress Treelist 会定期抛出 HideException?

c# - 在字符串集合中搜索的最快方法

c# - 在 Mvc.Controller 中使用服务器

c# - 如何使用 LINQ 过滤字符串 []?

javascript - 无法缩放 UIWebView

javascript - Chartjs v7.0 带插件缩放,使用 "drag"模式时效果奇怪。

javascript - 圆形包装中的文本路径无法正确缩放

c# - 如何使用linq语句进行查询?

c# - MonoTouch 资源