Search code examples
c#visual-studiowinformspanel

Windows Forms - Zooming in and out in Panel


I have made something like a drawing app but I need to implement a function to zoom in/out with using the right mouse button. I have added zooming but it zooms at the left-top corner. I tried to zoom in at given coordinates but neither of tries were successful.

    float zoom = 1f;

    private void canvasPanel_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.ScaleTransform(zoom, zoom);
        DrawShapesFromListOnPaint(e);
    }
    // ...
    private void canvasPanel_MouseClick(object sender, MouseEventArgs e) 
    { // For Right Click Zooming
        switch (e.Button)
        {
            case MouseButtons.Right:
                {
                    if (zoomed)
                    {
                        zoom -= 1;
                        zoomed = false;
                    }
                    else
                    {
                        zoom += 1;
                        zoomed = true;
                        zoomPoint = canvasPanel.PointToClient(Cursor.Position);
                    }
                    canvasPanel.Invalidate();
                }
                break;
            case MouseButtons.Left:
                // ...
                break;
        }
    }

Solution

  • As Hans Passant said, you also need a TranslateTransform() call. I wrote an example, left click to zoom in, right click to zoom out, please refer to:

    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    
    namespace ZoomingTest
    {
      public partial class Form1 : Form
      {
        public Form1() {
          InitializeComponent();
        }
    
        private Matrix transform = new Matrix();
        private float m_dZoomscale = 1.0f;
        public const float _dScrollValue = 0.1f;
    
        private void panel1_Paint(object sender, PaintEventArgs e) {
          Graphics g = e.Graphics;
          g.Transform = transform;
          Pen mypen = new Pen(Color.Red, 5);
          Rectangle rect = new Rectangle(10, 10, 30, 30);
          e.Graphics.DrawRectangle(mypen, rect);
        }
    
        //protected override void OnMouseWheel(MouseEventArgs mea) {
        //  panel1.Focus();
        //  if (panel1.Focused == true && mea.Delta != 0)
        //  {
        //    // Map the Form-centric mouse location to the PictureBox client coordinate system
        //    Point pictureBoxPoint = panel1.PointToClient(this.PointToScreen(mea.Location));
        //    ZoomScroll(pictureBoxPoint, mea.Delta > 0);
        //  }
        //}
    
        private void ZoomScroll(Point location, bool zoomIn) {
          // Figure out what the new scale will be. Ensure the scale factor remains between
          // 1% and 1000%
          float newScale = Math.Min(Math.Max(m_dZoomscale + (zoomIn ? _dScrollValue : -_dScrollValue), 0.1f), 10);
    
          if (newScale != m_dZoomscale)
          {
            float adjust = newScale / m_dZoomscale;
            m_dZoomscale = newScale;
    
            // Translate mouse point to origin
            transform.Translate(-location.X, -location.Y, MatrixOrder.Append);
    
            // Scale view
            transform.Scale(adjust, adjust, MatrixOrder.Append);
    
            // Translate origin back to original mouse point.
            transform.Translate(location.X, location.Y, MatrixOrder.Append);
    
            panel1.Invalidate();
          }
        }
    
        private void panel1_MouseClick(object sender, MouseEventArgs e) {
          panel1.Focus();
    
          Point pictureBoxPoint = panel1.PointToClient(this.PointToScreen(e.Location));
    
          if (panel1.Focused == true && e.Button == MouseButtons.Left)
          {
            // Left click to zoom in
            ZoomScroll(pictureBoxPoint, true);
          }
          else if (panel1.Focused == true && e.Button == MouseButtons.Right)
          {
            // Right click to zoom out
            ZoomScroll(pictureBoxPoint, false);
          }
        }
      }
    }
    

    The effect is as follows:

    enter image description here