views:

75

answers:

2

I have all the necessary code to move and click the mouse via C# code, but I don't want to just set the mouse position to X and Y; that will look jerky. Instead, I want to have a smooth transition from point X1, Y1 to point X2, Y2 over Z seconds. Similar to keyframing.

I'm looking for a method similar to this:

public void TransitionMouse(int x, int y, double durationInSecs)

It will just smoothly move the mouse from its current position to x and y in durationInSecs seconds. I have a function called:

public void MoveMouse(int x, int y)

That moves the mouse to x, y immediately.


EDIT

Thanks for the help guys! Here's the finished, and tested, code:

    [DllImport("user32.dll")]
    static extern bool SetCursorPos(int X, int Y);

    public void TransitionMouseTo(double x, double y, double durationSecs)
    {
        double frames = durationSecs*100;

        PointF vector = new PointF();
        PointF mousePos = Cursor.Position;

        vector.X = (float)((x - mousePos.X) / frames);
        vector.Y = (float)((y - mousePos.Y) / frames);

        for (int i = 0; i < frames; i++)
        {
            SetCursorPos((int)(mousePos.X += vector.X), (int)(mousePos.Y += vector.Y));
            Thread.Sleep((int)((durationSecs / frames) * 1000.0));
        }
    }
A: 

really depend on your definition of smooth, however most algorithm of "smooth" motion use spline to interpolate between 2 or more data points.

this could help http://geekswithblogs.net/JuanDoNeblo/archive/2007/10/25/Data-Interpolation-with-SPLINE-in-Csharp.aspx

dvhh
+3  A: 

You could do this in several ways. One option would be to calculate the vector required to move the mouse every frame and apply it over the time period to the mouse position.

So, if we are at position 5,5 and want to move to 20,30 over 10 frames, our vector would be the following:

val = (target - start) / frames;

x = (20 - 5) / 10; y = (30 - 5) / 10;

Vector = 1.5,2.5

Then, in your TransitionMouse method, you apply the vector to the mouse position slowly over whatever duration you wish, using the Thread.Sleep method to control the speed. The code might look like this:

public void TransitionMouseTo(int x, int y, int durationSecs)
{
    int frames = 10;

    PointF vector = new PointF();

    vector.X = (x - Cursor.Position.X) / frames;
    vector.Y = (y - Cursor.Position.Y) / frames;  

    for (int i = 0; i < frames; i++)
    {
        Point pos = Cursor.Position;

        pos.X += vector.X;
        pos.Y += vector.Y;

        Cursor.Position = pos;

        Thread.Sleep((durationSecs / frames) * 1000);
    }
}

Another way of doing it would be to use Bresenhams algorithm to calculate all the points the mouse cursor will move through and then loop through each point and apply it to the cursor again using Thread.Sleep to keep the timing correct.

Steve

Steve_
-1 is harsh for me, but "Cursor.Position.X += vector.X" and "Cursor.Position.Y += vector.Y" won't work.
Bolu
Sorry, you are correct. I've altered it.
Steve_
Works like a charm! Thanks!
TheAdamGaskins
Might I add that you can't set Cursor.Position, you'd have to use the Win32 function SetCursorPos. But after changing that, it works! :D
TheAdamGaskins
OK, I thought you could, but you get the idea :). I must confess I didn't test the code before posting it.
Steve_
@TheAdamGaskins, can you post your working code of TransitionMouseTo function?
Bolu
Yep, sure! I'll update the main post with it.
TheAdamGaskins
@TheAdamGaskins, Thanks for your code. I think you can just use Cursor.Position=new Point((int)(mousePos.X += vector.X), (int)(mousePos.Y += vector.Y)) to replace the SetCursorPos line.
Bolu
oh, yep, that works too
TheAdamGaskins