缩放后重新计算面板 AutoScrollPosition
Recompute Panel AutoScrollPosition after zoom
在 Panel 中嵌入 PictureBox 的 C# 表单应用程序,当图像和 PictureBox 需要水平或垂直滚动时,按照其他帖子中的建议利用 Panel AutoScroll。想要缩放图像并重新计算 AutoScrollPosition 以在缩放后保持相同的点可见。可以将图片框放大一倍,然后重新复制源图,实现缩放。但 AutoScrollPosition 保持不变,因此在缩放之前可见的内容已移出屏幕。 如何重新计算 AutoScrollPosition 以在缩放后保持图像焦点?
三种典型的缩放类型:
- 放大到中心,由缩放按钮触发
- 放大到鼠标位置,通过单击或滚轮触发
- 通过绘制矩形放大到矩形
我假设典型设置:A PictureBox
设置为 SizeMode=Zoom
嵌套 在 Panel
中 AutoScroll=true
和缩放注意保持 Image
和 PictureBox
的 纵横比 相等 .
让我们从介绍术语开始:
- 有一个
Image
我们称之为位图和 - 显示为
PictureBox
;我们称它为 canvas.. - ..嵌套在一个
Panel
中,我们称之为frame
用户友好的缩放需要一个固定点,也就是一个固定点。
对于 1) 它是 frame 的中心,对于 2) 它是鼠标位置,对于 3) 它是矩形的中心。
缩放前我们计算旧的缩放比例,固定点在帧 , canvas中的不动点最后是位图中的不动点.
缩放后我们计算新的缩放比例和canvas中的新固定点。最后我们用它来移动canvas带上固定的canvas点到固定的帧点.
这里是放大到(当前)中心的例子;这是两个按钮的常见点击事件,它只会将缩放比例加倍和减半。
更细粒度的因素当然更容易实现;更好的是固定的缩放级别列表,就像 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
这不仅困难,因为它们的值有点古怪,但也不会适应其他缩放类型。