C++ 平稳地移动鼠标

C++ 平稳地移动鼠标,c++,winapi,easing,C++,Winapi,Easing,我正在尝试使用WinAPI中的mouse\u event函数移动用户鼠标。这是我的代码: while (LeftMouseDown) { POINT cursorPos; GetCursorPos(&cursorPos); //X Axis And Y Axis is DWORD Array mouse_event(MOUSEEVENTF_MOVE, xaxis[iCount], yaxis[iCount],

我正在尝试使用WinAPI中的
mouse\u event
函数移动用户鼠标。这是我的代码:

    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);
    }

它工作得很好,但问题是我希望代码平滑移动,因为函数会立即传送光标,我不希望这样,我希望它是平滑过渡或类似的东西。

看着代码,你的鼠标会每200毫秒跳一个像素

    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);
        }
    }
while(LeftMouseDown)
{
点游标;
GetCursorPos(&cursorPos);
//X轴和Y轴为DWORD阵列
int i;
对于(i=0;i<20;i++)
{
鼠标事件(MOUSEEVENTF_MOVE,(xaxis[icount]-cursorPos.x)/20,(yaxis[icount]-cursorPos.y)/20,0,0);
iCount++;
睡眠(10);
}
}

从外观上看,您正试图以平滑的方式在点的路径上移动

如果是这样的话,那么你必须沿着时间的路径插值

基本上,这个想法是首先获得路径的总长度。然后,在更新时间时,通过总持续时间和经过的时间量获得总距离。最后,你找到两个点,其中获得的距离在中间某个地方。然后你只需沿着这两点插值就可以得到一个相对精确的点

使用该类,您可以传递路径的点和持续时间,以指定要沿路径移动多长时间。然后,您只需通过时间间隔对其进行更新

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
#包括
#包括
#ifndef MOVER_H
#定义移动器
结构点{
int x,y;
点(整数x,整数y)
:x(x_uu),y(y_u){
}
点():点(0,0){
}
};
班级搬运工{
公众:
结构点数据{
浮动总额;
浮动距离;
p1点;
p2点;
PointData()
:总计(0.f),
距离(0.f){
}
点数据(浮点总数、浮点距离、点p1、点p2)
:总计,
距离(distance),,
p1(p1),
p2(p2){
}
};
使用TimePoint=std::chrono::微秒;
私人:
std::向量m_点;
std::向量m_距离;
时间点m_持续时间;
时间点m_已过;
浮动长度;
公众:
移动器(std::initializer_列表点,时间点持续时间=std::chrono::微秒(2000000));
模板
移动器(iter\U t开始,iter\U t结束,时间点持续时间=std::chrono::微秒(2000000))
:m_点(开始、结束),
m_持续时间(持续时间),
已用分钟数(标准时间:毫秒数(0)){
updateLength();
}
移动器(const Mover&)=默认值;
移动器和运算符=(常量移动器-)=默认值;
点更新(时间点增量);
bool isComplete()常量;
无效设置持续时间(时间点持续时间);
TimePoint getDuration()常量;
TimePoint getappeased()常量;
私人:
void updateLength();
};
#endif//MOVER\u 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;  
}
#包括“Mover.h”
#包括
#包括
移动器::移动器(std::初始值设定项\列表点、时间点持续时间)
:移动器(points.begin()、points.end()、持续时间)
{
}
点移动器::更新(时间点增量)
{
常量自动比较=[](左浮点、常量点数据和右浮点){
返回左<右。总计;
};
m_经过=标准::分钟(m_经过+增量,m_持续时间);
常量浮点长度=(静态_转换(m_已用.count())/静态_转换(m_duration.count())*m_长度;
auto&data=*std::prev(std::上限(m_distance.begin(),m_distance.end(),length,comparison));
常量浮点百分比=(长度-data.total)/data.distance;
点-点(data.p1.x+percent*(data.p2.x-data.p1.x),data.p1.y+percent*(data.p2.y-data.p1.y));
返回点;
}
布尔移动器::isComplete()常量
{
返回m_duration==m_已用时间;
}
无效移动器::设置持续时间(时间点持续时间)
{
m_持续时间=持续时间;
}
移动器::时间点移动器::getDuration()常量
{
返回m_持续时间;
}
移动器::时间点移动器::GetExpressed()常量
{
返回m_已过;
}
void移动器::updateLength()
{
自动距离=[](浮动x1、浮动y1、浮动x2、浮动y2)->{
返回标准::sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
};
浮动长度=0.f;
对于(std::size_t index=0;(index+1)
示例

#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;
    }
}
#包括
#包括“Mover.h”
int main(){
向量点{0,0},{100100};
移动器移动(points.begin(),points.end());
自动t1=std::chrono::稳定时钟::现在();
而(!move.isComplete()){
自动t2=std::chrono::稳定时钟::现在();
自动点=move.update(std::chrono::duration_cast(t2-t1));

我知道这已经很晚了,但我还是回答吧。 在进行golang时,我使用了一个名为robot.go的库,在那里,它们有一个平滑输入的函数。因此,如果您需要,可以将其用作参考。

随着时间的推移插入位置。每秒更新5次位置。至少快4倍,这样看起来会很平滑。也许你想使用
MOUSEEVENTF\u MOVE | MOUSEEVENTF\u ABSOLUTE
而不是
MOUSEEVENTF\u MOVE
。阅读“备注”我试过将光标位置更改为0,0你不能移动鼠标。你只能在显示屏上移动光标。我觉得这个答案完全错了。请再读一遍问题,然后再重新回答。我不明白如果你需要猜测,你是提交答案的错误人。同样,如果你无法解释艾恩,问题是什么,或者你的解决方案是如何解决的,你错了