title: C# Cursor Position on Matrix Transformed Image
body: <p>I need help on Finding the Position on the Image that the user Double Clicked on.</p>
  <p>I can get the Position on the Control from the MouseEventArgs but need to Convert it to the Image dimensions. The Images has been Zoomed and Panned using a new custom control.</p>
  <p>The Zoom and Pan Works Likes a Charm (Based on <a href="https://web.archive.org/web/20141229192708/http://bobpowell.net/zoompicbox.aspx" rel="nofollow noreferrer">ZoomPicBox by Bob Powell</a>)
  I get a position but it is Total Off from where I click, it seems to be off by a factor but I cant figure what it is.
  The Double Click Event Code, I have tried it myself (commented out before the matrix), but had the same effect, the Vector2 Comment is a reference I found from <a href="https://gamedev.stackexchange.com/questions/21681/how-to-get-mouse-position-relative-to-the-map">Xna</a></p>
  <pre><code>    protected override void OnMouseDoubleClick(MouseEventArgs e)
      {
          if (e != null)
          {
              if (e.Button == MouseButtons.Left)
              {
                  //_ImgDoubleClick.X = (int)(e.Location.X / this.Zoom) - this.AutoScrollPosition.X;
                  //_ImgDoubleClick.Y = (int)(e.Location.Y / this.Zoom) - this.AutoScrollPosition.Y;
  
                  using (Matrix mx = new Matrix(_zoom, 0, 0, _zoom, 0, 0))
                  {
                      mx.Translate(this.AutoScrollPosition.X / _zoom, this.AutoScrollPosition.Y / _zoom);
  
                      //Vector2 worldPosition = Vector2.Transform(mousePosition, Matrix.Invert(viewMatrix));
                      mx.Invert();
                      Point worldPosition = VectorTransform(e.Location, mx);
  
                      _ImgDoubleClick.X = worldPosition.X;
                      _ImgDoubleClick.Y = worldPosition.Y;
                  }
              }
  
          }            
          
          
          base.OnMouseDoubleClick(e);
      }
  
      //-------------------------------------
      private Point VectorTransform(Point vector, Matrix matrix)
      {
          //var tempX = (matrix.M11 * vector.X) + (matrix.M21 * vector.Y) + matrix.M31;
          //var tempY = (matrix.M12 * vector.X) + (matrix.M22 * vector.Y) + matrix.M32;
  
          int tempX = (int)((matrix.Elements[0] * vector.X) + (matrix.Elements[2] * vector.Y) + matrix.Elements[4]);
          int tempY = (int)((matrix.Elements[1] * vector.X) + (matrix.Elements[3] * vector.Y) + matrix.Elements[5]);
  
          return new Point(tempX, tempY);
      }
  </code></pre>
  <p>Below is the On paint Event</p>
  <pre><code>protected override void OnPaint(PaintEventArgs e)
  {
  //if no image, don't bother
  if (_image == null)
  {
      base.OnPaintBackground(e);
      return;
  }
  //Set up a zoom matrix
  using (Matrix mx = new Matrix(_zoom, 0, 0, _zoom, 0, 0))
  {
      if (e != null)
      {
          //now translate the matrix into position for the scrollbars
          mx.Translate(this.AutoScrollPosition.X / _zoom, this.AutoScrollPosition.Y / _zoom);
          //use the transform
          e.Graphics.Transform = mx;
          //and the desired interpolation mode
          e.Graphics.InterpolationMode = _interpolationMode;
          //Draw the image ignoring the images resolution settings.
          e.Graphics.DrawImage(_image, new Rectangle(0, 0, this._image.Width, this._image.Height), 0, 0, _image.Width, _image.Height, GraphicsUnit.Pixel);
      }
  }
  //mx.Dispose();
  base.OnPaint(e);
  }
  </code></pre>
  <p>The Zoom Factor Setup</p>
  <pre><code>    public float Zoom
      {
          get
          {
              return _zoom;
          }
          set
          {
              if (value &lt; 0 || value &lt; 0.00001)
                  value = 0.00001f;
              _zoom = value;
              UpdateScaleFactor();
              Invalidate();
          }
      }
  
      //----------------------------------
      /// &lt;summary&gt;
      /// Calculates the effective size of the image
      ///after zooming and updates the AutoScrollSize accordingly
      /// &lt;/summary&gt;
      private void UpdateScaleFactor()
      {
          if (_image == null)
              this.AutoScrollMinSize = this.Size;
          else
          {
              this.AutoScrollMinSize = new Size(
                (int)(this._image.Width * _zoom + 0.5f),
                (int)(this._image.Height * _zoom + 0.5f)
                );
          }
      }
  </code></pre>
  <p>The using Statement from my control.</p>
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.ComponentModel;
  </code></pre>