Recompute Panel AutoScrollPosition after zoom

前端 未结 1 1569
南旧
南旧 2021-01-25 12:55

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

相关标签:
1条回答
  • 2021-01-25 13:23

    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.

    0 讨论(0)
提交回复
热议问题