找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 136|回复: 9

办公软件WPS的JSA中模拟鼠标单击/双击/右击

[复制链接]
发表于 8 小时前 | 显示全部楼层 |阅读模式
本帖最后由 cutebe 于 2026-4-22 17:11 编辑

办公软件WPS的表格:通过ExecuteExcel4Macro调用WinAPI实现

函数:
  1. function 操作鼠标(操作数组){        //移动1        //左键2|4        //右键8|16
  2.         let 操作组数=操作数组.length;
  3.         let 结构字节数=对象字节数(操作数组[0]);        /*****计算结构对象字节数*****/
  4.         let 总字节=结构字节数*操作组数;
  5.         const 数组缓冲=new ArrayBuffer(总字节);
  6.         for(let i=0;i<操作组数;i++){
  7.                 结构对象填入数组缓冲(数组缓冲,i*结构字节数,操作数组[i]);        /*****对象转数组缓冲*****/
  8.         }
  9.         const 执行宏调用=ExecuteExcel4Macro;        //申请内存
  10.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${总字节},${0x3000},4)`);
  11.         数据写入内存(内存地址,数组缓冲,总字节);        /*****写入鼠标操作结构*****/        //执行鼠标操作
  12.         鼠标操作结果=执行宏调用(`CALL("User32","SendInput","JJJJ",${操作组数},${内存地址},${结构字节数})`);
  13.         if(!鼠标操作结果){console.log("错误代码:"+执行宏调用(`CALL("Kernel32","GetLastError","I")`));}
  14.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  15. }
复制代码


测试函数:
  1. function 鼠标单击测试(){
  2.         let 左键按下=鼠标操作对象(0,0,2),左键松开=鼠标操作对象(0,0,4);        /*****生成单个对象*****/
  3.         let 点击=鼠标操作对象(0,0,2|4),右击=鼠标操作对象(0,0,8|0x10);

  4.         alert("移动鼠标指针到将要点击的位置,按【空格】或【回车】记下坐标。");
  5.         var 鼠标指针坐标=获取鼠标位置();        /*****获取鼠标指针坐标*****/
  6.         var 水平=鼠标指针坐标[0],垂直=鼠标指针坐标[1];
  7.         alert("将点击的鼠标位置:("+水平+","+垂直+"),确定则进行点击操作。");
  8.         设置鼠标位置(水平,垂直);        /*****移动鼠标指针*****/
  9.         let 单击=[点击];
  10.         操作鼠标(单击);        /*****鼠标单击操作*****/
  11. }
  12. function 鼠标双击测试(){
  13.         alert("移动鼠标指针到将要双击的位置,按【空格】或【回车】记下坐标。");
  14.         var 鼠标指针坐标=获取鼠标位置();        /*****获取鼠标指针坐标*****/
  15.         var 水平=鼠标指针坐标[0],垂直=鼠标指针坐标[1];
  16.         alert("将双击的鼠标位置:("+水平+","+垂直+"),确定则进行双击操作。");
  17.         设置鼠标位置(水平,垂直);        /*****移动鼠标指针*****/
  18.         
  19.         let 点击=鼠标操作对象(0,0,2|4);
  20.         let 双击=[点击,点击];
  21.         操作鼠标(双击);        /*****鼠标双击操作*****/
  22. }
  23. function 鼠标右键测试(){
  24.         let 右击=鼠标操作对象(0,0,8|0x10);
  25.         操作鼠标([右击]);        /*****鼠标右击操作*****/
  26. }
  27. function 鼠标拖拽测试(){
  28.         console.clear();console.log("移动鼠标指针到将要拖拽的位置(如标题栏),再按F5执行函数。");
  29.         let 左键按下=鼠标操作对象(0,0,2),左键松开=鼠标操作对象(0,0,4);
  30.         
  31.         //Win10
  32.         //let 移动鼠标=鼠标操作对象(50,-20,1);        //相对右移上移
  33.         //let 拖拽=[左键按下,移动鼠标,左键松开];
  34.         //操作鼠标(拖拽);        /*****鼠标操作*****/
  35.         let 移动松开=鼠标操作对象(50,-20,1|4);        //相对右移上移
  36.         操作鼠标([左键按下,移动松开]);        /*****鼠标操作*****/
  37.         
  38.         //Win7
  39.         //操作鼠标([左键按下]);        /*****鼠标操作*****/
  40.         //var 鼠标指针坐标=获取鼠标位置();        /*****获取鼠标指针坐标*****/
  41.         //var 水平=鼠标指针坐标[0],垂直=鼠标指针坐标[1];
  42.         //设置鼠标位置(水平+50,垂直-20);        /*****移动鼠标指针*****/
  43.         //操作鼠标([左键松开]);        /*****鼠标操作*****/
  44. }
复制代码


调用函数:
  1. function 数据写入内存(内存地址,数组缓冲,字节数){
  2.         const 数据操作=new DataView(数组缓冲);
  3.         let 偏移=i=0,待写数据=[],写入字节=[];
  4.         while(字节数>偏移){
  5.                 if(字节数-偏移>=4){待写数据[i]=数据操作.getInt32(偏移,true);写入字节[i]=4;i++;偏移+=4;}
  6.                 else{if(字节数-偏移>=2){待写数据[i]=数据操作.getInt16(偏移,true);写入字节[i]=2;i++;偏移+=2;}
  7.                 else{if(字节数-偏移==1){待写数据[i]=数据操作.getInt8(偏移,true);写入字节[i]=1;i++;偏移++;}}}
  8.         }
  9.         const 执行宏调用=ExecuteExcel4Macro;
  10.         for(偏移=i=0;i<写入字节.length;i++){        //写入
  11.                 执行宏调用(`CALL("Kernel32","RtlMoveMemory","2JNJ",${内存地址+偏移},${待写数据[i]},${写入字节[i]})`);
  12.                 偏移+=写入字节[i];
  13.         }
  14. }
  15. function 设置鼠标位置(水平,垂直){
  16.         const 执行宏调用=ExecuteExcel4Macro;
  17.         var 结果=执行宏调用(`CALL("User32","SetCursorPos","AJJ",${水平},${垂直})`);
  18.         return 结果;        //成功返回true
  19. }
  20. function 获取鼠标位置(){        //返回坐标数组[x,y]
  21.         const 执行宏调用=ExecuteExcel4Macro;
  22.         //逻辑值 GetCursorPos([输出]结构 屏幕坐标指针)
  23.         var 坐标结构=执行宏调用(`CALL("User32","GetCursorPos","1E",0)`);        //参数:4+4字节坐标结构
  24.         const 缓冲区=new ArrayBuffer(8); //8字节对应64位
  25.         const 数据操作=new DataView(缓冲区);        //操作对象
  26.         数据操作.setFloat64(0,坐标结构);        //(操作)写入64位数
  27.         let 坐标=[];
  28.         坐标[0]=数据操作.getInt32(4);        //取32位坐标x
  29.         坐标[1]=数据操作.getInt32(0);        //取32位坐标y
  30.         return 坐标;
  31. }
  32. function 鼠标操作对象(水平,垂直,操作){
  33.         class 鼠标操作 {        //类
  34.                 constructor(水平,垂直,动作){        //类的构造方法,用于构造属性
  35.                         this.输入类型1 = [4,0],        //鼠标0        //字节数,数据
  36.                         this.水平坐标2 = [4,水平],        //相对坐标,即移动量
  37.                         this.垂直坐标3 = [4,垂直],
  38.                         this.滚轮转量4 = [4,0],
  39.                         this.输入操作5 = [4,动作],        //右键按下8        绝对坐标0x8000
  40.                         this.时间戳值6 = [4,0],        //系统确定
  41.                         this.扩展数据7 = [4,0]
  42.                 }
  43.         };
  44.         let 鼠标对象 = new 鼠标操作(水平,垂直,操作);
  45.         return 鼠标对象;
  46. }
  47. function 对象字节数(结构对象){
  48.         let 对象数据字节数=0;
  49.         for (let 属性名 in 结构对象) {
  50.                 if (结构对象.hasOwnProperty(属性名)) {
  51.                         对象数据字节数+=结构对象[属性名][0];        //累加字节数
  52.                 }
  53.         }
  54.         return 对象数据字节数;
  55. }
  56. function 结构对象填入数组缓冲(数组缓冲,偏移,结构对象){
  57.         const 数据操作=new DataView(数组缓冲);
  58.         let 字节数,待填数据;
  59.         for (let 属性名 in 结构对象) {
  60.                 if (结构对象.hasOwnProperty(属性名)) {
  61.                         字节数=结构对象[属性名][0],待填数据=结构对象[属性名][1];
  62.                         if(字节数==4){数据操作.setInt32(偏移,待填数据,true);}        //小端序
  63.                         else{if(字节数==2){数据操作.setInt32(偏移,待填数据,true);}
  64.                         else{if(字节数==1){数据操作.setInt32(偏移,待填数据,true);}}}
  65.                         偏移+=字节数;
  66.                 }
  67.         }
  68. }
复制代码


主要是为了验证JSA中调用WinAPI时 输出型结构参数 是否可获取,输入型结构参数 是否也可以通过内存来引用
 楼主| 发表于 7 小时前 | 显示全部楼层
另一种鼠标事件方式:
  1. function 鼠标事件单击测试(){
  2.         const 执行宏调用=ExecuteExcel4Macro;
  3.         执行宏调用(`CALL("User32","mouse_event","JJJJJJ",${2|4},0,0,0,0)`);        //左键单击
  4. }
  5. function 鼠标事件双击测试(){
  6.         const 执行宏调用=ExecuteExcel4Macro;
  7.         执行宏调用(`CALL("User32","mouse_event","JJJJJJ",${2|4},0,0,0,0)`);        //左键双击
  8.         执行宏调用(`CALL("User32","mouse_event","JJJJJJ",${6},0,0,0,0)`);
  9. }
  10. function 鼠标事件右击测试(){
  11.         const 执行宏调用=ExecuteExcel4Macro;
  12.         执行宏调用(`CALL("User32","mouse_event","JJJJJJ",${8|0x10},0,0,0,0)`);        //右键
  13. }
复制代码


鼠标移动:MouseEvent_Move     = 0x0001;

左键按下:MouseEvent_LeftDown = 0x0002;        //左键单击:0x2|0x4
左键松开:MouseEvent_LeftUp   = 0x0004;

右键按下:MouseEvent_RightDown= 0x0008;        //右击:0x8|0x10
右键松开:MouseEvent_RightUp  = 0x0010;

绝对坐标:MouseEvent_Absolute = 0x8000;
回复

使用道具 举报

发表于 7 小时前 | 显示全部楼层
多谢楼主分享!!!
回复

使用道具 举报

发表于 7 小时前 | 显示全部楼层
看看怎样。
回复

使用道具 举报

发表于 6 小时前 | 显示全部楼层
谢楼主分享
回复

使用道具 举报

发表于 5 小时前 | 显示全部楼层
要保存为什么文件?

点评

打开WPS表格,新建后,在工具》开发工具》查看代码,模块里粘贴代码。  发表于 4 小时前

评分

参与人数 1无忧币 +5 收起 理由
yyz2191958 + 5

查看全部评分

回复

使用道具 举报

发表于 5 小时前 | 显示全部楼层
有何应用场景

点评

暂时没有  发表于 4 小时前
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层
请问大神这个的用途是什么呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1|闽公网安备35020302032614号 )

GMT+8, 2026-4-22 23:42

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表