none
How to scale & transform mouse location RRS feed

  • Question

  • Is there a set of transform and scaling functions for scaling the mouse handler routine's e.Location member?  I'm usnig the Graphic.PageScale and Graphics.TranslateTransform(..) to pan and zoom my client area.  This works just fine, but the mouse coordinates are still in standard client coordinates and scaling.  I'm assuming there must be a simple way of handling this ?

    Thanks
    Saturday, March 6, 2010 2:38 AM

Answers

  • Thanks for testing this out.  I was getting a bit suspicious that none of the three seemed to give the expected results.

    I looked into ScaleTransform(..), but the problem with this and others is they require a GDI context to instantiate, which is not present in any of the mouse event handlers.  By the time one creates the context and gets it in order (transform and scaling), it's beginning to look like my MouseToWorld( funciton ) is the better solution.

    Given how common it is to have to coordinate mouse location with the client area, I'm very surprised no internal provision was made compensate for this.

    Anyway, thanks again for your help.  I appreciate it.

    RWey
    • Marked as answer by RWey Sunday, March 7, 2010 2:12 AM
    Sunday, March 7, 2010 2:12 AM

All replies

  • You can use Graphics.TransformPoints method to apply the transformation associated with the Graphics to abitrary points which you specify.  In your case it would be the mouse point that you want to tranform.


    Saturday, March 6, 2010 5:41 PM
  • OK, that makes sense, but I'm not getting the expected results.  Here's a test I ran:   ( notes follow )

     

    private void tabProcessControl_MouseDown( object sender, MouseEventArgs e )
    {
    	Point wp = MouseToWorld( e.Location );
    
    	Graphics g = tabControl1.CreateGraphics();  // tabProcessControl is a tab within TabControl tabControl1.
    	g.PageScale = pageScale;
    	g.TranslateTransform( xformPoint.X, xformPoint.Y );
    
    	Point[] pa = new Point[ 1 ];
    	pa[ 0 ] = e.Location;
    	g.TransformPoints( CoordinateSpace.World, CoordinateSpace.World, pa );
    	pa[ 0 ] = e.Location;
    	g.TransformPoints( CoordinateSpace.World, CoordinateSpace.Page, pa );
    	pa[ 0 ] = e.Location;
    	g.TransformPoints( CoordinateSpace.World, CoordinateSpace.Device, pa );
    
    // ...
    }
    
    Point MouseToWorld( Point location )
    {
    	return new Point( (int)( (float)( location.X ) / pageScale - xformPoint.X + 0.5F ),
    			(int)( (float)( location.Y ) / pageScale - xformPoint.Y + 0.5F ) );
    }

    The function MouseToWorld(.) is what I'm currently using, where pageScale and xformPoint store my current zoom and offset, respectively.  These are the two factors I use in my Paint handler to set my Graphics.PageScale and Graphics.TranslateTransform().

    As can be seen in the MouseDown handler, I first make a call to my MouseToWorld(.) function to establish the known good converted point.  I then take the same mouse point and run it through the three possible Graphics.TransformPoints(..) and none of the three yield anything close to the results my MouseToWorld(.)) function yields.

    One might ask why, if I have a function that works, I'm even asking how to do this.  My answer is that I'd like to find the proper way to handle this, rather than manually grunting a conversion function.

    Thanks for your help.
    Saturday, March 6, 2010 7:26 PM
  • > g.TransformPoints( CoordinateSpace.World, CoordinateSpace.Device, pa );

    This one sounds like it should work.  However, I was able to reproduce what you describe.  Doesn't look like TransformPoints is paying attention to the page transformation.  Don't know why.

    I think you might be able to replace the use of PageScale with a call to ScaleTransform(pageScale, pageScale) instead.  The same results as MouseToWorld were returned in that case when I tried it out.

    (ASIDE:  Graphics implements IDisposable.  When you use CreateGraphics, be sure to call Dispose on it or even better use a "using" block.  The graphics contexts are a limited resource...)
    Saturday, March 6, 2010 11:18 PM
  • Thanks for testing this out.  I was getting a bit suspicious that none of the three seemed to give the expected results.

    I looked into ScaleTransform(..), but the problem with this and others is they require a GDI context to instantiate, which is not present in any of the mouse event handlers.  By the time one creates the context and gets it in order (transform and scaling), it's beginning to look like my MouseToWorld( funciton ) is the better solution.

    Given how common it is to have to coordinate mouse location with the client area, I'm very surprised no internal provision was made compensate for this.

    Anyway, thanks again for your help.  I appreciate it.

    RWey
    • Marked as answer by RWey Sunday, March 7, 2010 2:12 AM
    Sunday, March 7, 2010 2:12 AM
  • Thank you soo much. 

    I tried to your MouseToWorld code example on my all mouseEventArgs and that is work greatly.

    I have a panel on my winforms application. Panel has a lot of creatable node, line. It didn't work every time i tried to ScaleTransform object. It was always different between mouse location and move/click location. And then i iplemented this code by using your example like that;

    var location = new Point((int)((float)e.Location.X / ZoomRatio), (int)((float)e.Location.Y / ZoomRatio));

    This is work fine for me.

    Thank you soo much again.. 

    Best regards.

    Friday, November 8, 2019 7:28 AM