如何在c#中的图片框中放大一点?

时间:2017-06-15 11:21:53

标签: c# winforms zoom 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 个答案:

答案 0 :(得分:3)

您所引用的答案无法奏效。我不知道为什么它被接受,也没有被投票。除了在过去的某个时间,显然也投票了。我不知道自己在想什么。

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

  1. 它使用直接传入的鼠标坐标,而不是将它们转换为PictureBox控件的坐标系。传递给OnMouseWheel()方法的坐标相对于Form本身,因此仅当PictureBox左上角与Form左上角重合时角落会起作用。
  2. 更有问题的是,代码完全滥用了Matrix.Scale()方法,为规模传递了似乎是 delta 的值,实际上是Scale()方法接受比例的因子。这有两个含义:
    • 传递负值是错误的,因为负值翻转坐标系,而不是缩小比例,
    • 传递增量值是错误的,因为传递的值将乘以当前缩放以获得新的缩放。
  3. 同样有问题的是,代码以错误的顺序应用矩阵变换,因为默认顺序是" prepend"而不是"追加" (我发现后者更自然可以使用,但我认为那些专门研究矩阵数学的人可以解释为什么默认是前者)。
  4. 还有一个相对较小的问题,即使忽略了上述内容,允许用户任意调整比例因子,最终也会导致超出范围的值。代码将规模限制在合理的范围内会更好。

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

    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