Recompute Panel AutoScrollPosition after zoom

陌路散爱 提交于 2019-12-02 15:01:27

问题


Have C# forms application with PictureBox embedded in Panel, to take advantage of Panel AutoScroll as suggested in other posts when image and thus PictureBox need to be scrolled horizontally or vertically. Want to zoom the image and recompute AutoScrollPosition to keep same Point visible after zooming. Can double size of PictureBox, then recopy source image, accomplishing zoom. But AutoScrollPosition remains unchanged, thus what was visible before zoom has moved off screen. How to recompute AutoScrollPosition to keep image focus after zoom?


回答1:


There are three typical types of zooming:

  1. zoom into the center, triggered by zoom buttons
  2. zoom into the mouse position, triggered by clicking or scroll-wheeling
  3. zoom into a rectangle, by drawing a rectangle

I assume the typical setup: A PictureBox set to SizeMode=Zoom nested in a Panel with AutoScroll=true and zooming that takes care to keep the aspect ratios of Image and PictureBox equal.

Let's start by introducing terminology:

  • There is an Image we call bitmap and
  • it is displayed by a PictureBox; let's call it canvas..
  • .. which is nested in a Panel we call frame

User-friendly zooming needs a fixed point, that is a point that shall stay put.

For 1) it is the center of the frame, for 2) it is the mouse location and for 3) it is the center of the rectangle.

Before zooming we calculate the old zoom ratio, the fixed point in the frame, the fixed point in the canvas and finally the fixed point in the bitmap.

After zoming we calculate the new zoom ratio and the new fixed point in the canvas. Finally we use it to move the canvas to bring the fixed canvas point to the fixed frame point.


Here is an example for zooming into the (current) center; it is a common click event for two buttons and it only doubles and halves the zoom ratio.

Much finer grained factors are of course simple to implement; even better is a fixed list of zoom levels, like Photoshop has!

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);
}

Note that while one can try to restore the relative AutoScrollValues this is not only hard, because their values are a little quirky but it is also won't be adaptable to the other zoom types.



来源:https://stackoverflow.com/questions/45148535/recompute-panel-autoscrollposition-after-zoom

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!