// // Created by misaki on 2026/1/25. // #pragma once #include #include #include #include #include #include #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 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 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 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& keys); /** * @brief 按下组合键(向量版本) * @param keys 键名向量 */ void hotkey(const std::vector& 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& 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& keys, double duration = 1.0, double pressRate = 5.0); } // namespace ExtendedFunc } // namespace AutoGUI