缩放后重新计算Panel AutoScrollPosition
拥有嵌入Panel中的PictureBox的C#表单应用程序,以便在图像和PictureBox需要水平或垂直滚动时,按照其他post中的建议利用Panel AutoScroll。 想要缩放图像并重新计算AutoScrollPosition以在缩放后保持相同的点可见。 可以双倍大小的PictureBox,然后重新复制源图像,完成缩放。 但是AutoScrollPosition保持不变,因此在缩放移出屏幕之前可见。 如何重新计算AutoScrollPosition以在缩放后保持图像焦点?
有三种典型的缩放类型:
- 缩放到中心,由缩放按钮触发
- 放大鼠标位置,通过单击或滚动触发
- 通过绘制矩形来放大矩形
我假设典型的设置: PictureBox
设置为SizeMode=Zoom
嵌套在Panel
, AutoScroll=true
和缩放,注意保持Image
和PictureBox
的宽高比 相等 。
让我们从介绍术语开始:
- 有一个我们称之为位图的
Image
- 它由
PictureBox
显示; 我们称它为帆布 .. - ..嵌套在我们称之为框架的
Panel
用户友好的缩放需要一个固定的点 ,这是一个应该保持的点。
1)它是框架的中心,2)它是鼠标位置,3)它是矩形的中心。
在缩放之前,我们计算旧的缩放比率, 帧中的固定点, canvas中的固定点以及最后位图中的固定点。
在zoming之后,我们计算新的缩放比率和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
但这不仅很难,因为它们的值有点古怪,但它也不适用于其他缩放类型。