Reputation:
I am aware of the MoveWindow() and SetWindowPos() functions. I know how to use them correctly. However, what I am trying to accomplish is move a window slowly and smoothly as if a user is dragging it.
I have yet to get this to work correctly. What I tried was getting the current coordinates with GetWindowRect() and then using the setwindow and movewindow functions, incrementing Right by 10 pixels each call.
Any ideas?
Here is what I had beside all my definitions.
while(1)
{
GetWindowRect(notepad,&window);
Sleep(1000);
SetWindowPos(
notepad,
HWND_TOPMOST,
window.top - 10,
window.right,
400,
400,
TRUE
);
}
Upvotes: 2
Views: 2800
Reputation: 159600
If you want smooth animation, you'll need to make it time-based, and allow Windows to process messages in between movements. Set a timer, and respond to WM_TIMER notifications by moving the window a distance based on the elapsed time since your animation started. For natural-looking movement, don't use a linear function for determining the distance - instead, try something like Robert Harvey's suggested function.
Pseudocode:
//
// animate as a function of time - could use something else, but time is nice.
lengthInMS = 10*1000; // ten second animation length
StartAnimation(desiredPos)
{
originalPos = GetWindowPos();
startTime = GetTickCount();
// omitted: hwnd, ID - you'll call SetTimer differently
// based on whether or not you have a window of your own
timerID = SetTimer(30, callback);
}
callback()
{
elapsed = GetTickCount()-startTime;
if ( elapsed >= lengthInMS )
{
// done - move to destination and stop animation timer.
MoveWindow(desiredPos);
KillTimer(timerID);
}
// convert elapsed time into a value between 0 and 1
pos = elapsed / lengthInMS;
// use Harvey's function to provide smooth movement between original
// and desired position
newPos.x = originalPos.x*(1-SmoothMoveELX(pos))
+ desiredPos.x*SmoothMoveELX(pos);
newPos.y = originalPos.y*(1-SmoothMoveELX(pos))
+ desiredPos.y*SmoothMoveELX(pos);
MoveWindow(newPos);
}
Upvotes: 5
Reputation: 180777
I found this code which should do what you want. It's in c#, but you should be able to adapt it:
increment a variable between 0 and 1 (lets call it "inc" and make it global) using small increments (.03?) and use the function below to give a smooth motion.
Math goes like this:
currentx=x1*(1-smoothmmoveELX(inc)) + x2*smoothmmoveELX(inc)
currenty=y1*(1-smoothmmoveELX(inc)) + y2*smoothmmoveELX(inc)
Code:
public double SmoothMoveELX(double x)
{
double PI = Atn(1) * 4;
return (Cos((1 - x) * PI) + 1) / 2;
}
http://www.vbforums.com/showthread.php?t=568889
Upvotes: 4
Reputation: 43217
If you are bored enough, you can do loopback VNC to drag the mouse yourself.
Now, as for why you would want to I don't know.
Upvotes: 0
Reputation: 180777
A naturally-moving window would accelerate as it started moving, and decelerate as it stopped. The speed vs. time graph would look like a bell curve, or maybe the top of a triangle wave. The triangle wave would be easier to implement.
As you move the box, you need to steadily increase the number of pixels you are moving the box each time through the loop, until you reach the halfway point between point a and point b, at which you will steadily decrease the number of pixels you are moving the box by. There is no special math involved; it is just addition and subtraction.
Upvotes: 2