title: C# Application to Zoom in/out the image in a PictureBox
body: <p>I am somewhat new to programming in general, but I am eager to learn more and I was wondering if anyone could possibly help me out with an idea.</p>
  
  <p>(<strong><em>main goal</em></strong>)</p>
  
  <p>I want to make a simple program that consists of a C# Windows Forms Application that displays a preset image (of 6000x6000 pixel dimensions, SizeMode set to Zoom so the entire image is visible on the form at once) in a PictureBox that will take up the entire form practically, save for a space at the bottom of the form where I want to display a TrackBar that will allow you to zoom the image in and out; as well as a horizontal scroll bar at the base of the PictureBox, and a vertical scroll bar on the right side of the PictureBox to scroll around the map when it is zoomed, and I wanted to be able to control these scroll bars by either clicking and dragging in a corresponding direction on the PictureBox (preferred but not sure if its possible) or by using the scroll wheel on the mouse (probably easier but once again not sure).</p>
  
  <p>(<strong><em>reference</em></strong>)</p>
  
  <p>[ <strong><em>Here is my form completed exactly as I described, with a 6000x6000 placement holder demo texture in a PictureBox using SizeMode Zoom, as an example</em></strong> - THIS HAS BEEN HANDLED, NEXT PART OF THE PROBLEM IS UPDATED BELOW:]</p>
  
  <p>(<strong><em>addendum</em></strong>)</p>
  
  <p>The only issue I am having is the code, as I am pretty much greenhorn in that department. I have been working to learn Visual Studio's workflow, but I really could use some help.</p>
  
  <p>Thank you so much in advance for anything you can help me with.</p>
  
  <p>UPDATE:</p>
  
  <p>After doing research on the subject and taking time to do some thinking, I have come up with the code listed below; but my problem is that when I pan my image too far, the image is allowed to be pulled too far over, thus exposing the panel behind it when the image is panned/pulled too far over to one corner. Also, when I zoom too far out, the image is allowed to become WAY smaller than the Picturebox.</p>
  
  <p><a href="https://i.stack.imgur.com/eT8eS.jpg" rel="nofollow noreferrer">Panning issue, the grey parts of the panel are the problem</a></p>
  
  <p><a href="https://i.stack.imgur.com/2lMKb.png" rel="nofollow noreferrer">Zoom issue, the grey parts of the panel are the problem</a></p>
  
  <p>So, my last question: How would I go about revising the code below to 'lock' the image that I am panning and zooming from being allowed to pan or zoom outside of its frame and expose the panel behind it?</p>
  
  <pre><code>public partial class ImageZoomMainForm : Form
  {
      Image img;
      Point mouseDown;
      int startx = 0;
      int starty = 0;
      int imgx = 0; 
      int imgy = 0;
  
      bool mousepressed = false;  
      float zoom = 1;
  
      public ImageZoomMainForm()
      {
  
          InitializeComponent();
          string imagefilename = @"..\..\ViewPort_MAIN.tif";
          img = Image.FromFile(imagefilename);
  
          Graphics g = this.CreateGraphics();
  
  
  
  
  
  
  
  
          zoom = ((float)pictureBox.Width / (float)img.Width) * (img.HorizontalResolution / g.DpiX);
  
          pictureBox.Paint += new PaintEventHandler(imageBox_Paint);
      }
  
      private void pictureBox_MouseMove(object sender, EventArgs e)
      {
          MouseEventArgs mouse = e as MouseEventArgs;
  
          if (mouse.Button == MouseButtons.Left)
          {
              Point mousePosNow = mouse.Location;
  
              int deltaX = mousePosNow.X - mouseDown.X; 
              int deltaY = mousePosNow.Y - mouseDown.Y;
  
              imgx = (int)(startx + (deltaX / zoom));  
              imgy = (int)(starty + (deltaY / zoom));
  
              pictureBox.Refresh();
          }
      }
  
      private void imageBox_MouseDown(object sender, EventArgs e)
      {
          MouseEventArgs mouse = e as MouseEventArgs;
  
          if (mouse.Button == MouseButtons.Left)
          {
              if (!mousepressed)
              {
                  mousepressed = true;
                  mouseDown = mouse.Location;
                  startx = imgx;
                  starty = imgy;
              }
          }
      }
  
      private void imageBox_MouseUp(object sender, EventArgs e)
      {
          mousepressed = false;
      }
  
      protected override void OnMouseWheel(MouseEventArgs e)
      {
          float oldzoom = zoom;
  
          if (e.Delta &gt; 0)
          {
              zoom += 0.1F;
          }
  
          else if (e.Delta &lt; 0)
          {
              zoom = Math.Max(zoom - 0.1F, 0.01F);
          }
  
          MouseEventArgs mouse = e as MouseEventArgs;
          Point mousePosNow = mouse.Location;
  
          int x = mousePosNow.X - pictureBox.Location.X;    
          int y = mousePosNow.Y - pictureBox.Location.Y;
  
          int oldimagex = (int)(x / oldzoom);  
          int oldimagey = (int)(y / oldzoom);
  
          int newimagex = (int)(x / zoom);     
          int newimagey = (int)(y / zoom);
  
          imgx = newimagex - oldimagex + imgx;  
          imgy = newimagey - oldimagey + imgy;
  
          pictureBox.Refresh();  
  
  
      }
  
      private void imageBox_Paint(object sender, PaintEventArgs e)
      {
          e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
          e.Graphics.ScaleTransform(zoom, zoom);
          e.Graphics.DrawImage(img, imgx, imgy);
      }
  
  
  
      protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
      {
          const int WM_KEYDOWN = 0x100;
          const int WM_SYSKEYDOWN = 0x104;
  
          if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
          {
              switch (keyData)
              {
                  case Keys.Right:
                      imgx -= (int)(pictureBox.Width * 0.1F / zoom);
                      pictureBox.Refresh();
                      break;
  
                  case Keys.Left:
                      imgx += (int)(pictureBox.Width * 0.1F / zoom);
                      pictureBox.Refresh();
                      break;
  
                  case Keys.Down:
                      imgy -= (int)(pictureBox.Height * 0.1F / zoom);
                      pictureBox.Refresh();
                      break;
  
                  case Keys.Up:
                      imgy += (int)(pictureBox.Height * 0.1F / zoom);
                      pictureBox.Refresh();
                      break;
  
                  case Keys.PageDown:
                      imgy -= (int)(pictureBox.Height * 0.90F / zoom);
                      pictureBox.Refresh();
                      break;
  
                  case Keys.PageUp:
                      imgy += (int)(pictureBox.Height * 0.90F / zoom);
                      pictureBox.Refresh();
                      break;
              }
          }
  
          return base.ProcessCmdKey(ref msg, keyData);
      }
  
      private void ImageZoomMainForm_Load(object sender, EventArgs e)
      {
  
      }
  }
  </code></pre>
  
  <p>}</p>