522 lines
14 KiB
C++
522 lines
14 KiB
C++
//
|
||
// Created by misaki on 2026/1/25.
|
||
//
|
||
#pragma once
|
||
|
||
#include <algorithm>
|
||
#include <string>
|
||
#include <utility>
|
||
#include <vector>
|
||
#include <map>
|
||
#include <initializer_list>
|
||
|
||
#include "Keyboard.h"
|
||
#include "Mouse.h"
|
||
#include "types.h"
|
||
|
||
namespace AutoGUI {
|
||
|
||
// 错误类型
|
||
class AutoGUIException : public std::exception {
|
||
private:
|
||
std::string message;
|
||
|
||
public:
|
||
explicit AutoGUIException(std::string msg) : message(std::move(msg)) {}
|
||
|
||
[[nodiscard]] const char* what() const noexcept override {
|
||
return message.c_str();
|
||
}
|
||
};
|
||
|
||
// 鼠标按钮枚举
|
||
enum class Button {
|
||
LEFT = 0,
|
||
RIGHT = 1,
|
||
MIDDLE = 2
|
||
};
|
||
|
||
// 将 Button 转换为 Robot::MouseButton
|
||
inline Robot::MouseButton toRobotButton(Button button) {
|
||
switch (button) {
|
||
case Button::LEFT: return Robot::MouseButton::LEFT_BUTTON;
|
||
case Button::RIGHT: return Robot::MouseButton::RIGHT_BUTTON;
|
||
case Button::MIDDLE: return Robot::MouseButton::CENTER_BUTTON;
|
||
default: return Robot::MouseButton::LEFT_BUTTON;
|
||
}
|
||
}
|
||
|
||
// 将 Button 枚举转换为字符串
|
||
inline std::string buttonToString(Button button) {
|
||
switch (button) {
|
||
case Button::LEFT: return "left";
|
||
case Button::RIGHT: return "right";
|
||
case Button::MIDDLE: return "middle";
|
||
default: return "left";
|
||
}
|
||
}
|
||
|
||
// 键名字符串到 Keyboard::SpecialKey 的映射
|
||
inline Robot::Keyboard::SpecialKey stringToSpecialKey(const std::string& key) {
|
||
static std::map<std::string, Robot::Keyboard::SpecialKey> keyMap = {
|
||
{"backspace", Robot::Keyboard::BACKSPACE},
|
||
{"enter", Robot::Keyboard::ENTER},
|
||
{"return", Robot::Keyboard::ENTER},
|
||
{"tab", Robot::Keyboard::TAB},
|
||
{"escape", Robot::Keyboard::ESCAPE},
|
||
{"esc", Robot::Keyboard::ESCAPE},
|
||
{"up", Robot::Keyboard::UP},
|
||
{"down", Robot::Keyboard::DOWN},
|
||
{"right", Robot::Keyboard::RIGHT},
|
||
{"left", Robot::Keyboard::LEFT},
|
||
{"win", Robot::Keyboard::META},
|
||
{"command", Robot::Keyboard::META},
|
||
{"cmd", Robot::Keyboard::META},
|
||
{"alt", Robot::Keyboard::ALT},
|
||
{"ctrl", Robot::Keyboard::CONTROL},
|
||
{"control", Robot::Keyboard::CONTROL},
|
||
{"shift", Robot::Keyboard::SHIFT},
|
||
{"capslock", Robot::Keyboard::CAPSLOCK},
|
||
{"f1", Robot::Keyboard::F1},
|
||
{"f2", Robot::Keyboard::F2},
|
||
{"f3", Robot::Keyboard::F3},
|
||
{"f4", Robot::Keyboard::F4},
|
||
{"f5", Robot::Keyboard::F5},
|
||
{"f6", Robot::Keyboard::F6},
|
||
{"f7", Robot::Keyboard::F7},
|
||
{"f8", Robot::Keyboard::F8},
|
||
{"f9", Robot::Keyboard::F9},
|
||
{"f10", Robot::Keyboard::F10},
|
||
{"f11", Robot::Keyboard::F11},
|
||
{"f12", Robot::Keyboard::F12},
|
||
{"space", Robot::Keyboard::BACKSPACE} // 特殊处理空格
|
||
};
|
||
|
||
std::string lower = key;
|
||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||
|
||
auto it = keyMap.find(lower);
|
||
if (it != keyMap.end()) {
|
||
return it->second;
|
||
}
|
||
|
||
// 如果是单个字符,直接返回(会在其他地方处理)
|
||
if (lower.length() == 1) {
|
||
// 这是单个字符键,不是特殊键
|
||
throw AutoGUIException("Unknown key: " + key);
|
||
}
|
||
|
||
throw AutoGUIException("Unknown key: " + key);
|
||
}
|
||
|
||
// 检查字符串是否是特殊键
|
||
inline bool isSpecialKey(const std::string& key) {
|
||
static std::vector<std::string> specialKeys = {
|
||
"backspace", "enter", "return", "tab", "escape", "esc",
|
||
"up", "down", "right", "left", "win", "command", "cmd",
|
||
"alt", "ctrl", "control", "shift", "capslock",
|
||
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
|
||
"space"
|
||
};
|
||
|
||
std::string lower = key;
|
||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||
|
||
return std::find(specialKeys.begin(), specialKeys.end(), lower) != specialKeys.end();
|
||
}
|
||
|
||
// 解决多屏幕移动鼠标问题
|
||
struct ScreenInfo {
|
||
int id; // 屏幕ID
|
||
int x, y; // 相对于虚拟桌面原点的偏移
|
||
int width, height;// 屏幕尺寸
|
||
bool isPrimary; // 是否主屏
|
||
};
|
||
|
||
// 获取所有屏幕信息
|
||
std::vector<ScreenInfo> getAllScreens();
|
||
|
||
// 获取当前鼠标所在的屏幕
|
||
ScreenInfo getCurrentScreen();
|
||
|
||
// 相对于当前屏幕移动鼠标(以当前屏幕左上角为原点)
|
||
void moveToOnCurrentScreen(int x, int y, double duration = 0.0);
|
||
|
||
// 获取指定屏幕的尺寸(替代原来的size(),支持多屏)
|
||
Robot::Point getScreenSize(int screenId = -1); // -1表示当前屏幕
|
||
|
||
|
||
// 主要 API 函数
|
||
/**
|
||
* @brief 移动鼠标到指定位置
|
||
* @param x 目标位置的X坐标
|
||
* @param y 目标位置的Y坐标
|
||
* @param duration 移动持续时间(秒),0表示立即移动
|
||
*/
|
||
void moveTo(int x, int y, double duration = 0.0);
|
||
|
||
/**
|
||
* @brief 相对移动鼠标
|
||
* @param xOffset X方向偏移量
|
||
* @param yOffset Y方向偏移量
|
||
* @param duration 移动持续时间(秒),0表示立即移动
|
||
*/
|
||
void moveRel(int xOffset, int yOffset, double duration = 0.0);
|
||
|
||
/**
|
||
* @brief 单击鼠标
|
||
* @param x 点击位置的X坐标,-1表示当前位置
|
||
* @param y 点击位置的Y坐标,-1表示当前位置
|
||
* @param button 鼠标按钮:left, right, middle
|
||
* @param clicks 点击次数
|
||
* @param interval 多次点击之间的间隔(秒)
|
||
*/
|
||
void click(int x = -1, int y = -1,
|
||
Button button = Button::LEFT,
|
||
int clicks = 1,
|
||
double interval = 0.0);
|
||
|
||
/**
|
||
* @brief 左键双击
|
||
* @param x 双击位置的X坐标,-1表示当前位置
|
||
* @param y 双击位置的Y坐标,-1表示当前位置
|
||
*/
|
||
void leftDouble(int x = -1, int y = -1);
|
||
|
||
/**
|
||
* @brief 右键单击
|
||
* @param x 点击位置的X坐标,-1表示当前位置
|
||
* @param y 点击位置的Y坐标,-1表示当前位置
|
||
*/
|
||
void rightSingle(int x = -1, int y = -1);
|
||
|
||
/**
|
||
* @brief 中键单击
|
||
* @param x 点击位置的X坐标,-1表示当前位置
|
||
* @param y 点击位置的Y坐标,-1表示当前位置
|
||
*/
|
||
void middleClick(int x = -1, int y = -1);
|
||
|
||
/**
|
||
* @brief 按下鼠标按钮
|
||
* @param button 要按下的鼠标按钮
|
||
* @param x 按下位置的X坐标,-1表示当前位置
|
||
* @param y 按下位置的Y坐标,-1表示当前位置
|
||
*/
|
||
void mouseDown(Button button = Button::LEFT, int x = -1, int y = -1);
|
||
|
||
/**
|
||
* @brief 释放鼠标按钮
|
||
* @param button 要释放的鼠标按钮
|
||
* @param x 释放位置的X坐标,-1表示当前位置
|
||
* @param y 释放位置的Y坐标,-1表示当前位置
|
||
*/
|
||
void mouseUp(Button button = Button::LEFT, int x = -1, int y = -1);
|
||
|
||
/**
|
||
* @brief 从指定位置拖动到另一个位置
|
||
* @param x1 起始位置的X坐标
|
||
* @param y1 起始位置的Y坐标
|
||
* @param x2 目标位置的X坐标
|
||
* @param y2 目标位置的Y坐标
|
||
* @param duration 拖动持续时间(秒),0表示立即拖动
|
||
* @param button 拖动时按住的鼠标按钮
|
||
*/
|
||
void drag(int x1, int y1, int x2, int y2,
|
||
double duration = 0.0,
|
||
Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 拖拽鼠标到指定位置
|
||
* @param x 目标位置的X坐标
|
||
* @param y 目标位置的Y坐标
|
||
* @param duration 拖拽持续时间(秒),0表示立即拖拽
|
||
* @param button 拖拽时按住的鼠标按钮
|
||
*/
|
||
void dragTo(int x, int y, double duration = 0.0, Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 相对拖拽鼠标
|
||
* @param xOffset X方向偏移量
|
||
* @param yOffset Y方向偏移量
|
||
* @param duration 拖拽持续时间(秒),0表示立即拖拽
|
||
* @param button 拖拽时按住的鼠标按钮
|
||
*/
|
||
void dragRel(int xOffset, int yOffset, double duration = 0.0, Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 获取当前鼠标位置
|
||
* @return 包含x,y坐标的Point结构体
|
||
*/
|
||
Robot::Point position();
|
||
|
||
/**
|
||
* @brief 滚动鼠标滚轮
|
||
* @param clicks 滚动量,正数向上滚动,负数向下滚动
|
||
* @param x 水平滚动量(Linux/macOS支持)
|
||
*/
|
||
void scroll(int clicks, int x = 0);
|
||
|
||
/**
|
||
* @brief 输入文本
|
||
* @param text 要输入的文本
|
||
* @param interval 字符之间的间隔时间(秒),0表示无间隔
|
||
* 注意:只支持ASCII字符
|
||
*/
|
||
void type(const std::string& text, double interval = 0.0);
|
||
|
||
/**
|
||
* @brief 按下并释放一个键
|
||
* @param key 键名(如:"a", "enter", "ctrl"等)
|
||
*/
|
||
void press(const std::string& key);
|
||
|
||
/**
|
||
* @brief 按下键(不释放)
|
||
* @param key 键名
|
||
*/
|
||
void keyDown(const std::string& key);
|
||
|
||
/**
|
||
* @brief 释放键
|
||
* @param key 键名
|
||
*/
|
||
void keyUp(const std::string& key);
|
||
|
||
/**
|
||
* @brief 按下组合键
|
||
* @param keys 键名列表,如 {"ctrl", "c"}
|
||
*/
|
||
void hotkey(const std::initializer_list<std::string>& keys);
|
||
|
||
/**
|
||
* @brief 按下组合键(向量版本)
|
||
* @param keys 键名向量
|
||
*/
|
||
void hotkey(const std::vector<std::string>& keys);
|
||
|
||
/**
|
||
* @brief 睡眠/等待
|
||
* @param seconds 等待的秒数
|
||
*/
|
||
void sleep(double seconds);
|
||
|
||
/**
|
||
* @brief 获取屏幕尺寸
|
||
* @return 包含屏幕宽度和高度的Point结构体
|
||
* @note 需要平台特定实现
|
||
* @note 注意:不提供屏幕管理功能,如果你有多个屏幕,那么返回的size可能是错误的,对于单个屏幕是没有影响的,对于获取屏幕尺寸,更加推荐使用Qt当中的接口
|
||
*/
|
||
Robot::Point size();
|
||
|
||
// 辅助函数
|
||
/**
|
||
* @brief 检查坐标是否有效
|
||
* @param x X坐标
|
||
* @param y Y坐标
|
||
* @return 如果坐标有效返回true
|
||
*/
|
||
bool isValidCoord(int x, int y);
|
||
|
||
/**
|
||
* @brief 将字符串转换为小写
|
||
* @param str 输入字符串
|
||
* @return 小写字符串
|
||
*/
|
||
std::string toLower(const std::string& str);
|
||
|
||
namespace ExtendedFunc {
|
||
/// drag拓展功能
|
||
/**
|
||
* @brief 从指定位置开始拖动一个矩形区域
|
||
* @param x1 矩形左上角X坐标
|
||
* @param y1 矩形左上角Y坐标
|
||
* @param width 矩形宽度
|
||
* @param height 矩形高度
|
||
* @param duration 拖动持续时间(秒)
|
||
* @param button 拖动时按住的鼠标按钮
|
||
*/
|
||
void dragRect(int x1, int y1, int width, int height,
|
||
double duration = 0.5, Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 拖动一个圆形区域(从中心开始到边缘)
|
||
* @param centerX 圆心X坐标
|
||
* @param centerY 圆心Y坐标
|
||
* @param radius 圆半径
|
||
* @param duration 拖动持续时间(秒)
|
||
* @param button 拖动时按住的鼠标按钮
|
||
*/
|
||
void dragCircle(int centerX, int centerY, int radius,
|
||
double duration = 0.5, Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 在区域内随机拖动(用于测试或自动化)
|
||
* @param x1 区域左上角X坐标
|
||
* @param y1 区域左上角Y坐标
|
||
* @param x2 区域右下角X坐标
|
||
* @param y2 区域右下角Y坐标
|
||
* @param minDuration 最小拖动持续时间(秒)
|
||
* @param maxDuration 最大拖动持续时间(秒)
|
||
* @param button 拖动时按住的鼠标按钮
|
||
*/
|
||
void dragRandomInArea(int x1, int y1, int x2, int y2,
|
||
double minDuration = 0.1, double maxDuration = 0.5,
|
||
Button button = Button::LEFT);
|
||
|
||
/// 文字输入扩展功能
|
||
/**
|
||
* @brief 模拟人类打字(带随机延迟和可能的错误)
|
||
* @param text 要输入的文本
|
||
* @param minDelay 最小延迟(秒)
|
||
* @param maxDelay 最大延迟(秒)
|
||
* @param errorRate 错误率(0.0-1.0)
|
||
*/
|
||
void typeHumanLike(const std::string& text, double minDelay = 0.05,
|
||
double maxDelay = 0.2, double errorRate = 0.0);
|
||
|
||
/**
|
||
* @brief 输入文本并回车
|
||
* @param text 要输入的文本
|
||
* @param interval 字符间隔
|
||
*/
|
||
void typewriteEnter(const std::string& text, double interval = 0.0);
|
||
|
||
/**
|
||
* @brief 输入多行文本
|
||
* @param lines 文本行数组
|
||
* @param interval 字符间隔
|
||
* @param lineDelay 行间延迟
|
||
*/
|
||
void typewriteLines(const std::vector<std::string>& lines,
|
||
double interval = 0.0, double lineDelay = 0.1);
|
||
|
||
/**
|
||
* @brief 输入当前日期时间
|
||
* @param format 时间格式(如:"%Y-%m-%d %H:%M:%S")
|
||
*/
|
||
void typeDateTime(const std::string& format = "%Y-%m-%d %H:%M:%S");
|
||
|
||
/// 键盘快捷键扩展功能
|
||
/**
|
||
* @brief 保存文件 (Ctrl+S)
|
||
*/
|
||
void saveFile();
|
||
|
||
/**
|
||
* @brief 打开文件 (Ctrl+O)
|
||
*/
|
||
void openFile();
|
||
|
||
/**
|
||
* @brief 新建文件 (Ctrl+N)
|
||
*/
|
||
void newFile();
|
||
|
||
/**
|
||
* @brief 复制 (Ctrl+C)
|
||
*/
|
||
void copy();
|
||
|
||
/**
|
||
* @brief 粘贴 (Ctrl+V)
|
||
*/
|
||
void paste();
|
||
|
||
/**
|
||
* @brief 剪切 (Ctrl+X)
|
||
*/
|
||
void cut();
|
||
|
||
/**
|
||
* @brief 全选 (Ctrl+A)
|
||
*/
|
||
void selectAll();
|
||
|
||
/**
|
||
* @brief 撤销 (Ctrl+Z)
|
||
*/
|
||
void undo();
|
||
|
||
/**
|
||
* @brief 重做 (Ctrl+Y 或 Ctrl+Shift+Z)
|
||
*/
|
||
void redo();
|
||
|
||
/**
|
||
* @brief 查找 (Ctrl+F)
|
||
*/
|
||
void find();
|
||
|
||
/**
|
||
* @brief 替换 (Ctrl+H)
|
||
*/
|
||
void replace();
|
||
|
||
/**
|
||
* @brief 打印 (Ctrl+P)
|
||
*/
|
||
void print();
|
||
|
||
/**
|
||
* @brief 关闭窗口 (Alt+F4 或 Ctrl+W)
|
||
*/
|
||
void closeWindow(bool useAltF4 = true);
|
||
|
||
/**
|
||
* @brief 切换窗口 (Alt+Tab)
|
||
* @param times 切换次数
|
||
*/
|
||
void switchWindow(int times = 1);
|
||
|
||
/**
|
||
* @brief 刷新 (F5)
|
||
*/
|
||
void refresh();
|
||
|
||
/// 游戏/自动化操作功能拓展
|
||
/**
|
||
* @brief 自动点击器(连续点击)
|
||
* @param x 点击位置X坐标
|
||
* @param y 点击位置Y坐标
|
||
* @param count 点击次数
|
||
* @param interval 点击间隔(秒)
|
||
* @param button 鼠标按钮
|
||
*/
|
||
void autoClicker(int x, int y, int count = 10, double interval = 0.1,
|
||
Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 连点器(按住连点)
|
||
* @param x 点击位置X坐标
|
||
* @param y 点击位置Y坐标
|
||
* @param duration 持续时间(秒)
|
||
* @param clickRate 点击频率(次/秒)
|
||
* @param button 鼠标按钮
|
||
*/
|
||
void rapidClicker(int x, int y, double duration = 1.0,
|
||
double clickRate = 10.0,
|
||
Button button = Button::LEFT);
|
||
|
||
/**
|
||
* @brief 按键连发(按住按键)
|
||
* @param key 按键名称
|
||
* @param duration 持续时间(秒)
|
||
* @param pressRate 按键频率(次/秒)
|
||
*/
|
||
void rapidKeyPress(const std::string& key, double duration = 1.0,
|
||
double pressRate = 10.0);
|
||
|
||
/**
|
||
* @brief 组合键连发
|
||
* @param keys 按键组合
|
||
* @param duration 持续时间
|
||
* @param pressRate 按键频率
|
||
*/
|
||
void rapidHotkey(const std::vector<std::string>& keys, double duration = 1.0,
|
||
double pressRate = 5.0);
|
||
|
||
} // namespace ExtendedFunc
|
||
|
||
} // namespace AutoGUI
|