顺利移动鼠标

时间:2018-04-20 14:21:11

标签: c++ winapi easing

我试图在WinAPI中使用mouse_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);
    }

它运作良好,但问题是我希望代码平滑移动,因为该功能瞬间传送光标而我不想要它,我希望它是平滑过渡或类似的东西

3 个答案:

答案 0 :(得分:0)

我知道这已经很晚了,但我不妨回答一下。 在做 golang 时,我使用了这个名为 robots.go 的库,在那里他们有一个可以平滑输入的函数。因此,如果您愿意,可以将其用作参考。 https://github.com/go-vgo/robotgo/blob/master/mouse/mouse_c.h

答案 1 :(得分:-1)

从它看起来,你试图以平滑的方式穿过一条点。

如果是这样,那么你将不得不通过时间插入该路径。

基本上,这个想法是你首先获得路径的总长度。然后,当您更新时间时,您将通过总持续时间和经过的时间获得总距离。最后,您会找到获得距离在中间某处的两个点。然后,您只需沿这两个点进行插值即可获得相对准确的点。

使用此类,您可以传递路径的点和持续时间,以指定您希望沿路径移动的时间。然后你只需要通过时间间隔更新它。

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

示例

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

值得一提的是,为了使用它,您将不得不跟踪时间以更新移动器。因此,可能值得实现一个Clock类或其他东西来跟踪你的时间。

此外,如果要沿相对于当前光标位置的路径移动,则只需将光标位置添加到活动路径点即可。

答案 2 :(得分:-2)

查看您的代码,您的鼠标将每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);
        }
    }