用途,减少腱鞘炎发生。鼠标坏了可以换,手废了,就别想当码农了。

  • 按住副按键1,自动连击鼠标左键
  • 单击副按键2,自动按住W键前进,再次单击副按键2,取消按住W键前进
  • 滚轮滚动,自动连击F键拾取物品
  • 单击键盘R_CTRL+P键,切换工具启动和停止

副按键是特殊按键。我这里的鼠标是 m618 plus。其他鼠标请自行改键码。

使用了 C++20 的 format 库,编译需要vs2019 开 lastest 编译。或者需要vs2022。
或者可以直接屏蔽掉那几句语句,不使用c++20特性。

仅提供完整代码,不提供已编译的程序。
一是不通用,二是都有现成的鼠标宏,不差我这个。
三是想学习原理的才会看这,既然想学习,那肯定有基础了。

编译后生成后,需要使用 管理员权限启动 才能发送按键到游戏中。
这是因为windows的限制,低等级程序不允许对高级别程序发送消息。

/*
* 用于原神的PC的工具
* 按住副按键1,自动连击鼠标左键
* 单击副按键2,自动按住W键前进,再次单击副按键2,取消按住W键前进
* 滚轮滚动,自动连击F键拾取物品
* 单击键盘R_CTRL+P键,切换工具启动和停止
*
* 用于减少腱鞘炎的发生概率。
*/#include <Windows.h>
#include <iostream>
#include <format>
#include <string>
#include <thread>
#include <mutex>
#include <list>
using namespace std;HHOOK keyboardHook = 0;
HHOOK mouseHook = 0;bool need_quit = false;
bool do_auto_left_click = false;
int n_auto_f_repeat = false;
bool do_auto_w_press = false;bool is_pause = true;// 简单的多线程日志打印工具,避免命令行无法打印字符时导致死锁
mutex log_mutex;
list<string> log_queue;void add_log_str(const string s)
{unique_lock<mutex>(log_mutex);while (log_queue.size() > 10)log_queue.pop_front();log_queue.push_back(s);
}bool get_log_str(string& s)
{if (log_queue.size() == 0)return false;unique_lock<mutex>(log_mutex);s = log_queue.front();log_queue.pop_front();return true;
}void log_run()
{while (!need_quit){string s;if (get_log_str(s)){cout << s << endl;}else{Sleep(500);}}
}
// -------------------------------------------------/*
* 对指定数值进行一些随机偏移
*/
int get_random_offset(int d1, int of1)
{float percent = rand() / (float)RAND_MAX;percent = percent * 2 - 1;d1 = d1 + of1 * percent;return d1;
}/*
* 自动连击左键线程体
*/
void auto_left_click_run()
{while (!need_quit){if (is_pause){Sleep(500);do_auto_left_click = false;continue;}if (do_auto_left_click){//cout << "Send left click." << endl;add_log_str("Send left click.");INPUT  Input ={ 0 };Input.type = INPUT_MOUSE;Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;    // 模拟按下SendInput(1, &Input, sizeof(INPUT));Sleep(get_random_offset(70, 30));Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;     // 模拟弹起SendInput(1, &Input, sizeof(INPUT));Sleep(get_random_offset(70, 30));}else{Sleep(100);}}
}/*
* 自动连击F键线程体
*/
void auto_press_f_run()
{while (!need_quit){if (is_pause){Sleep(500);n_auto_f_repeat = 0;continue;}// 限制最大连按3次。n_auto_f_repeat = min(n_auto_f_repeat, 3);if (n_auto_f_repeat > 0){n_auto_f_repeat -= 1;//cout << "Send F key." << endl;add_log_str("Send F key.");INPUT  Input ={ 0 };Input.type = INPUT_KEYBOARD;Input.ki.wVk = 'F';Input.ki.wScan = VkKeyScanA('F');//Input.ki.dwFlags = KEYEVENTF_SCANCODE;Input.ki.dwFlags = 0;SendInput(1, &Input, sizeof(INPUT));Sleep(get_random_offset(70, 30));//Input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;Input.ki.dwFlags = KEYEVENTF_KEYUP;SendInput(1, &Input, sizeof(INPUT));Sleep(get_random_offset(70, 30));}else{Sleep(100);}}
}/*
* 自动按住W键线程体
*/
void auto_toggle_press_w_run()
{while (!need_quit){if (is_pause){Sleep(500);do_auto_w_press = false;continue;}if (do_auto_w_press){do_auto_w_press = false;INPUT  Input ={ 0 };Input.type = INPUT_KEYBOARD;Input.ki.wVk = 'W';Input.ki.wScan = VkKeyScanA('F');if (GetAsyncKeyState('W') & 0x8000){//cout << "Send W up key." << endl;add_log_str("Send W up key.");Input.ki.dwFlags = KEYEVENTF_KEYUP;SendInput(1, &Input, sizeof(INPUT));}else{//cout << "Send W down key." << endl;add_log_str("Send W down key.");Input.ki.dwFlags = 0;}SendInput(1, &Input, sizeof(INPUT));Sleep(get_random_offset(70, 30));}else{Sleep(100);}}
}LRESULT CALLBACK KbHookCallback(int code, WPARAM wParam, LPARAM lParam)
{KBDLLHOOKSTRUCT* ks = (KBDLLHOOKSTRUCT*)lParam;//auto s = format("vkCode:0x{:x} wParam:0x{:x} flags:0x{:x}", ks->vkCode, wParam, ks->flags);//cout << s << endl;if (ks->vkCode == 'P' && (GetAsyncKeyState(VK_RCONTROL) & 0x8000)){if (wParam == 0x101){is_pause = !is_pause;if (is_pause)//cout << "工作已暂停" << endl;add_log_str("工作已暂停");else//cout << "工作已恢复" << endl;add_log_str("工作已恢复");}return 1;}return CallNextHookEx(0, code, wParam, lParam);
}LRESULT CALLBACK MsHookCallback(int code, WPARAM wParam, LPARAM lParam)
{MSLLHOOKSTRUCT* ms = (MSLLHOOKSTRUCT*)lParam;// 当鼠标输入特殊键时,mouseData 不为 0。if (ms->mouseData != 0){auto s = format("mouseData:0x{:x} wParam:0x{:x} flags:0x{:x}", ms->mouseData, wParam, ms->flags);//cout << s << endl;add_log_str(s);//cout << hex << "mouseData:0x" << ms->mouseData << "wParam:0x" << wParam << "flags:0x" << ms->flags << endl;// 按下副按键1时,自动连击左键if (ms->mouseData == 0x20000){if (wParam == 0x20b){// 按键按下do_auto_left_click = true;return 1;}else if (wParam == 0x20c){// 按键弹起do_auto_left_click = false;return 1;}}// 按下副按键2时,切换自动跑步键else if (ms->mouseData == 0x10000){if (wParam == 0x20b){// 按键按下do_auto_w_press = true;return 1;}//else if (wParam == 0x20c)//{// // 按键弹起//   do_auto_w_press = false;// return 1;//}}// 滚动滚轮时,自动点击F键else if (ms->mouseData == 0xff880000 || ms->mouseData == 0x780000){if (wParam == 0x20a){// 滚动n_auto_f_repeat += 1;// 滚轮滚动事件不要吞掉。// return 1;}}}return CallNextHookEx(0, code, wParam, lParam);
}int main()
{cout << "用于原神PC版的自动连击工具。\n\n按住副按键1,自动连击鼠标左键。\n点击副按键2,自动切换按住W键\n滚动滑轮,自动连击F键\nR_CTRL+P键切换开始和停止\n\n用于减少腱鞘炎的发生概率。\n" << endl;keyboardHook = SetWindowsHookExA(WH_KEYBOARD_LL, KbHookCallback, GetModuleHandleA(0), 0);if (keyboardHook == 0){cout << "挂钩键盘失败" << endl;return -1;}mouseHook = SetWindowsHookExA(WH_MOUSE_LL, MsHookCallback, GetModuleHandleA(0), 0);if (mouseHook == 0){cout << "挂钩鼠标失败" << endl;return -1;}// 启动连击工作线程auto t = thread(auto_left_click_run);auto t2 = thread(auto_press_f_run);auto t3 = thread(auto_toggle_press_w_run);auto t4 = thread(log_run);cout << "程序正常运行" << endl;cout << "按下 R_CTRL+P 组合键开始工作" << endl;//不可漏掉消息处理,不然程序会卡死MSG msg;while (GetMessageA(&msg, 0, 0, 0)){TranslateMessage(&msg);DispatchMessageW(&msg);}need_quit = true;UnhookWindowsHookEx(keyboardHook);UnhookWindowsHookEx(mouseHook);cout << "程序正常退出。" << endl;return 0;
}

自动连击左键,F键和自动按住W键工具相关推荐

  1. 【工具】向日葵远程控制之后键盘失效、自动锁定按住Alt键

    在使用向日葵软件远程控制过别人的电脑后,偶尔会出现一个BUG,就是自己键盘的ALT自动锁定了,好像始终按着ALT键不放,导致键盘无法使用. 主要原因就是,在远程控制时,使用了 Alt + Tab 键. ...

  2. ssm框架逻辑删除mysql_MybatisPlus--CRUD接口及主键增长策略、自动填充、乐观锁更新数据...

    目录 一.insert 1.插入操作 2.主键策略 二.update 1.根据Id更新操作 2.自动填充 3.乐观锁 三.select 1.根据id查询记录 2.通过多个id批量查询 3.简单的条件查 ...

  3. oracle实现主键自增长及自动生成策略

    文章目录 一 自增主键 两种方法可以设置主键: 自增长主键 唯一序列 一 自增主键 方法一:通过序列以及触发器实现主键自增长 适用于直接使用JDBC连接数据库,这种方式将主键自增长的任务完全交给数据库 ...

  4. html无间隔字幕滚动,js实现文字超过显示宽度每间隔1s自动向左滚动显示

    html: 文字如果超出了宽度自动向左滚动文字如果超出了宽度自动向左滚动.我是一个粉刷匠,粉刷本领强,我要把那新房子刷的更漂亮 js: var wrapper = document.getElemen ...

  5. 三位数自动递增编号函数_Excel单元格自动填充编号、序列、18位长数字与数字+字母+数字...

    在 Excel 中,用拖动的办法可以实现单元格自动填充编号,即数字会自动递增,既可以向下拖也可以向右拖,向那里拖,数字往那递增:这个方法适用于自动填充短编号,如果要自动填充长序列,再用此方法就不好实现 ...

  6. AHK-UMSS框架 (AHK通用修饰键解决方案,任何键都是修饰键)

    AHK-UMSS框架 (AHK通用修饰键解决方案,任何键都是修饰键) 1 #Warn 2 #NoEnv ; # 禁用环境变量检查:不检查空变量是否为"环境变量",可以极大地提高效率 ...

  7. linux 函数自动补全,Shell脚本中实现自动补全功能

    对于Linuxer来说,自动补全是再熟悉不过的一个功能了.当你在命令行敲下部分的命令时,肯定会本能地按下Tab键补全完整的命令,当然除了命令补全之外,还有文件名补全. Bash-completion ...

  8. 三位数自动递增编号函数_EXCEL中序号自动增加(如何避免隐藏行)?excel自动填充序号...

    excel表格中如何自动顺序填充序号 首先打开Excel 2007,创建如图所内容.当家也可以根据自己的实际情选择练习的内容.在此为了上的需要,特制作两列,第一列就"序号",第二列 ...

  9. 计算机基础---03Excel篇(入门,身份证筛选出生年月,自动填充功能,表格排序,自动筛选,高级筛选,数据有效性,求和)

    1.Excel 1.1 快速入门 说明一:一个Excel工作簿可以有很多工作表,点击+可以添加工作表: 工作表重命名:双击或者右键重命名. 给工作表标签添加颜色:不同的工作表标签可以代表轻重缓急,代表 ...

最新文章

  1. Unity easyTouch移动代码(参考)
  2. MySql数据备份与恢复
  3. java中文件选择对话框
  4. 朴素贝叶斯(naive bayes)
  5. 计算机网络2020秋--第二次测试
  6. dllregisterserver找不到入口点_厨房间漏水找不到漏水点,厨房上面漏水 | 影楼
  7. 用汉明距离进行图片相似度检测的Java实现
  8. go语言渐入佳境[10]-function
  9. paip.eclipse忽然启动报错的解决
  10. nuget 下载nupkg 以及依赖包
  11. cad怎么去除drawing1_CAD工具栏下边那行显示DraWing1的没了,如何找回?
  12. 群晖硬盘已损毁 Linux 修复,通用解决方案:修复Synology系统硬盘损坏
  13. token是什么意思
  14. 你办培训机构还不知道教育培训管理系统?
  15. POCO C++库学习和分析 -- 序
  16. 视觉C-部分技术文档
  17. 关于亚健康(KK记)
  18. cron定时任务详解
  19. 上班族怎么创业?白领一族创业当老板!
  20. CAM350 常用快捷键及简单操作问题

热门文章

  1. echarts图表无数据无时,在页面显示暂无数据
  2. win10怎么用计算机算进制,Win10系统计算器如何转换进制-win10系统下各进制转换的方法 - 河东软件园...
  3. G-08 魔王语言解释 (20 分)
  4. 站长说说之SEO让流量翻倍的策略分享
  5. vn.py项目安装经验分享
  6. 苹果mp3软件_这几款苹果APP也许你会用得着,赶紧下载试试看!
  7. HDU2159.FATE-完全背包
  8. python基础_面向对象进阶
  9. php生成CAD图纸,CAD怎么创建块?CAD创建块的命令
  10. 微信支付宝借刷脸支付抢占线下支付市场