c# - 缩放后重新计算面板 AutoScrollPosition

标签 c# winforms autoscroll

在面板中嵌入 PictureBox 的 C# 表单应用程序,以便在图像和 PictureBox 需要水平或垂直滚动​​时利用其他帖子中建议的面板自动滚动。想要缩放图像并重新计算 AutoScrollPosition 以在缩放后保持相同的点可见。可以将PictureBox放大一倍,然后重新复制源图像,实现缩放。但 AutoScrollPosition 保持不变,因此缩放之前可见的内容已移出屏幕。 如何重新计算 AutoScrollPosition 以在缩放后保持图像焦点?

最佳答案

缩放有三种典型类型:

  1. 通过缩放按钮触发放大到中心
  2. 放大鼠标位置,通过单击或滚轮触发
  3. 通过绘制矩形来放大矩形

我假设典型的设置:A PictureBox设置为SizeMode=Zoom 嵌套PanelAutoScroll=true缩放时要注意保持Image纵横比PictureBox 等于

让我们首先介绍术语:

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

用户友好的缩放需要一个固定点,即一个应保持不动的点。

对于 1) 它是框架的中心,对于 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这不仅很难,因为它们的值有点奇怪,而且它也无法适应其他缩放类型。

关于c# - 缩放后重新计算面板 AutoScrollPosition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45148535/

相关文章:

c# - 存储C#的静态类内存分配

c# - 如何访问 DataRepeater 中的控件

android - 下拉刷新自动滚动在 Android 中无法正常工作

python - 如何等待页面自动滚动完成

javascript - 使用 javascript 自动滚动定期从网站上抓取和下载所有图像

c# - DirectoryEntry 在尝试使用安全端口连接 ldap 服务器时出现 com 异常

c# - 如何对 WPF 用户控件的 View 模型进行单元测试

c# - 如何在 C# 中使用 win2D.uwp 将文本写入图像时旋转文本?

c# - datagridview 中一个单元格中的多行

c# - 以派生形式更改标签文本,其中标签位于基本形式