Reputation: 181
I'm trying to move the user mouse using mouse_event
function in WinAPI. This is my code:
while (LeftMouseDown)
{
POINT cursorPos;
GetCursorPos(&cursorPos);
//X Axis And Y Axis is DWORD Array
mouse_event(MOUSEEVENTF_MOVE, xaxis[iCount], yaxis[iCount], 0, 0);
iCount++;
Sleep(200);
}
It's working good but the problem is that I want the code smooth movement, because the function teleports the cursor instantly and I don't want that, I want it to be smooth transition or something like that.
Upvotes: 0
Views: 3300
Reputation: 162
I know this is very late but I might as well answer it. while doing golang I used this library called robot.go and over there they have a function that does the smooth input. So if you want you can use that as a reference. https://github.com/go-vgo/robotgo/blob/master/mouse/mouse_c.h
Upvotes: 1
Reputation: 1013
From what it looks like, you are trying to move across a path of points in a smooth manner.
If so, then you are going to have to interpolate along that path via time.
Essentially, the idea is that you first obtain the total length of the path. Then as you are updating time you obtain a total distance via the total duration and the elapsed amount of time. Finally, you find the two points where the obtained distance is somewhere in the middle. Then you simply interpolate along those two points to get a relatively accurate point.
With this class you can pass the points for the path and a a duration to specify how long you would like to be moving along the path for. Then you would simply update it via time intervals.
Mover.h
#include <chrono>
#include <vector>
#ifndef MOVER_H
#define MOVER_H
struct Point {
int x, y;
Point(int x_, int y_)
: x(x_), y(y_) {
}
Point() : Point(0, 0) {
}
};
class Mover {
public:
struct PointData {
float total;
float distance;
Point p1;
Point p2;
PointData()
: total(0.f),
distance(0.f) {
}
PointData(float total, float distance, Point p1, Point p2)
: total(total),
distance(distance),
p1(p1),
p2(p2) {
}
};
using TimePoint = std::chrono::microseconds;
private:
std::vector<Point> m_points;
std::vector<PointData> m_distances;
TimePoint m_duration;
TimePoint m_elapsed;
float m_length;
public:
Mover(std::initializer_list<Point> points, TimePoint duration = std::chrono::microseconds(2000000));
template<typename iter_t>
Mover(iter_t begin, iter_t end, TimePoint duration = std::chrono::microseconds(2000000))
: m_points(begin, end),
m_duration(duration),
m_elapsed(std::chrono::milliseconds(0)) {
updateLength();
}
Mover(const Mover&) = default;
Mover& operator=(const Mover&) = default;
Point update(TimePoint delta);
bool isComplete() const;
void setDuration(TimePoint duration);
TimePoint getDuration() const;
TimePoint getElapsed() const;
private:
void updateLength();
};
#endif // MOVER_H
Mover.cpp
#include "Mover.h"
#include <algorithm>
#include <cmath>
Mover::Mover(std::initializer_list<Point> points, TimePoint duration)
: Mover(points.begin(), points.end(), duration)
{
}
Point Mover::update(TimePoint delta)
{
const auto comparison = [](float left, const PointData& right) {
return left < right.total;
};
m_elapsed = std::min(m_elapsed + delta, m_duration);
const float length = (static_cast<float>(m_elapsed.count()) / static_cast<float>(m_duration.count())) * m_length;
auto& data = *std::prev(std::upper_bound(m_distances.begin(), m_distances.end(), length, comparison));
const float percent = (length - data.total) / data.distance;
Point point(data.p1.x + percent * (data.p2.x - data.p1.x), data.p1.y + percent * (data.p2.y - data.p1.y));
return point;
}
bool Mover::isComplete() const
{
return m_duration == m_elapsed;
}
void Mover::setDuration(TimePoint duration)
{
m_duration = duration;
}
Mover::TimePoint Mover::getDuration() const
{
return m_duration;
}
Mover::TimePoint Mover::getElapsed() const
{
return m_elapsed;
}
void Mover::updateLength()
{
auto distance = [](float x1, float y1, float x2, float y2) -> float{
return std::sqrt(((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
};
float length = 0.f;
for (std::size_t index = 0; (index + 1) < m_points.size(); ++index) {
const float dist = distance(m_points[index].x, m_points[index].y, m_points[index + 1].x, m_points[index + 1].y);
m_distances.emplace_back(length, dist, m_points[index], m_points[index + 1]);
length += dist;
}
m_length = length;
}
Example
#include <iostream>
#include "Mover.h"
int main() {
std::vector<Point> points{ { 0, 0 }, { 100, 100 } };
Mover move(points.begin(), points.end());
auto t1 = std::chrono::steady_clock::now();
while (!move.isComplete()) {
auto t2 = std::chrono::steady_clock::now();
auto point = move.update(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1));
std::cout << point.x << ' ' << point.y;
t1 = t2;
}
}
It's worth mentioning that in order to use this you are going to have to keep track of the time in order to update the mover. So it's probably worth implementing a Clock class or something to keep track of the time for you.
Also, if you want to move along the path relative to the current cursor position, then you would have to simply add the cursor position to the active path point.
Upvotes: 2
Reputation: 11
looking at your code your mouse will jump pixels every 200 ms.
while (LeftMouseDown)
{
POINT cursorPos;
GetCursorPos(&cursorPos);
//X Axis And Y Axis is DWORD Array
int i;
for (i = 0; i < 20; i++)
{
mouse_event(MOUSEEVENTF_MOVE, (xaxis[icount]-cursorPos.x)/20, (yaxis[icount]-cursorPos.y)/20, 0, 0);
iCount++;
Sleep(10);
}
}
Upvotes: -1