缩放后重新计算Panel AutoScrollPosition

时间:2017-07-17 15:49:56

标签: c# winforms autoscroll

具有嵌入Panel中的PictureBox的C#表单应用程序,以便在图像和PictureBox需要水平或垂直滚动​​时,按照其他帖子中的建议利用Panel AutoScroll。想要缩放图像并重新计算AutoScrollPosition以在缩放后保持相同的点可见。可以双倍大小的PictureBox,然后重新复制源图像,完成缩放。但是AutoScrollPosition保持不变,因此在缩放移出屏幕之前可见。 如何重新计算AutoScrollPosition以在缩放后保持图像聚焦?

1 个答案:

答案 0 :(得分:1)

有三种典型的缩放类型:

  1. 放大中心,由缩放按钮触发
  2. 放大鼠标位置,通过点击或滚动
  3. 触发
  4. 通过绘制矩形
  5. 放大矩形

    我假设典型设置:PictureBox设置为SizeMode=Zoom 嵌套 Panel AutoScroll=true并进行缩放以保持谨慎ImagePictureBox 等于宽高比

    让我们先介绍一下术语:

    • 有一个Image我们称之为 位图
    • PictureBox显示;我们称之为 canvas ..
    • ..嵌套在Panel我们称之为 框架

    用户友好的缩放需要一个固定点,这是一个值得留下的点。

    对于1)它是 的中心,2)它是鼠标位置,3)它是矩形的中心。

    在缩放之前,我们计算旧缩放比率 框架中的固定点 canvas ,最后是 位图 中的固定点。

    在zoming之后,我们计算新缩放比率以及 画布 中的新固定点。最后,我们使用它来移动 画布 ,将固定的画布点带到固定的画面点

    以下是放大(当前)中心的示例; 这是两个按钮的常见点击事件,它只是缩放比例的两倍和一半。

    许多细粒度因素当然很容易实现;更好的是缩放级别的固定列表,就像Photoshop一样!

    private void zoom_Click(object sender, EventArgs e)
    {
        PictureBox canvas = pictureBox1;
        Panel frame = panel1;
    
        // Set new zoom level, depending on the button
        float zoom = sender == btn_ZoomIn ? 2f : 0.5f;
    
        // calculate old ratio:
        float ratio = 1f * canvas.ClientSize.Width / canvas.Image.Width;
        // calculate frame fixed pixel:
        Point fFix = new Point( frame.Width / 2,  frame.Height / 2);
        // calculate the canvas fixed pixel:
        Point cFix =  new Point(-canvas.Left + fFix.X, -canvas.Top + fFix.Y );
        // calculate the bitmap fixed pixel:
        Point iFix = new Point((int)(cFix.X / ratio),(int)( cFix.Y / ratio));
    
        // do the zoom
        canvas.Size = new Size( (int)(canvas.Width *  zoom), (int)(canvas.Height *  zoom) );
    
        // calculate new ratio:
        float ratio2 = 1f * canvas.ClientSize.Width / canvas.Image.Width;
        // calculate the new canvas fixed pixel:
        Point cFix2 = new Point((int)(iFix.X * ratio2),(int)( iFix.Y * ratio2));
        // move the canvas:
        canvas.Location = new Point(-cFix2.X + fFix.X, -cFix2.Y + fFix.Y);
    }
    

    注意虽然可以尝试恢复相对AutoScrollValues,但这不仅很难,因为它们的值有点古怪但它也不适应其他缩放类型。