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

办公软件WPS的JSA中模拟键盘输入

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
办公软件WPS的表格:通过ExecuteExcel4Macro调用WinAPI实现

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

测试:键盘输入测试();  //执行函数前,请先打开一个记事本,将鼠标指针停在记事本窗口上方

测试及调用函数:
  1. function 键盘输入测试(){
  2.         //执行函数前,请先打开一个记事本,将鼠标指针停在记事本窗口上方
  3.         let 点击=鼠标操作对象(2|4);
  4.         操作鼠标([点击]);        /*****鼠标单击操作*****/

  5.         let 字符串="WuYou.Net";        //无忧论坛,将网址输入到记事本
  6.         let 字符数组=字符串.split(''),按键数组=[];
  7.         for(let i=0;i<字符串.length;i++){
  8.                 var 字符=字符数组[i];
  9.                 if(字符>='a' && 字符<='z'){字符=字符.toUpperCase();}
  10.                 按键数组[i]=键盘操作对象(字符);
  11.         }
  12.         操作键盘(按键数组);        /*****键盘操作*****/
  13. }

  14. function 键盘操作对象(键码){
  15.         class 键盘操作 {        //类
  16.                 constructor(按键,动作){        //类的构造方法,用于构造属性
  17.                         this.输入类型1 = [4,1],        //键盘1        //字节数,数据
  18.                         this.虚拟键码2 = [4,按键],        //同ASCII码
  19.                         this.键扫描码3 = [4,0],
  20.                         this.输入操作4 = [4,动作],        //按键弹起2        启用扫描码8
  21.                         this.时间戳值5 = [4,0],        //系统确定
  22.                         this.扩展信息6 = [4,0],
  23.                         this.数据填充x = [4,0]        //都是4*7=28字节,不足部分补足
  24.                 }
  25.         };
  26.         if(键码>='A'&&键码<='Z'){键码=键码.charCodeAt(0);}
  27.         if(键码=='.'){键码=0xBE;}
  28.         let 键盘对象 = new 键盘操作(键码,4|2);        //统一码0x4|2键弹起
  29.         return 键盘对象;
  30. }
  31. function 鼠标操作对象(操作){
  32.         class 鼠标操作 {        //类
  33.                 constructor(动作){        //类的构造方法,用于构造属性
  34.                         this.输入类型1 = [4,0],        //鼠标0        //字节数,数据
  35.                         this.水平坐标2 = [4,0],        //相对坐标,即移动量
  36.                         this.垂直坐标3 = [4,0],
  37.                         this.滚轮转量4 = [4,0],
  38.                         this.输入操作5 = [4,动作],        //右键按下8        绝对坐标0x8000
  39.                         this.时间戳值6 = [4,0],        //系统确定
  40.                         this.扩展数据7 = [4,0]
  41.                 }
  42.         };
  43.         let 鼠标对象 = new 鼠标操作(操作);
  44.         return 鼠标对象;
  45. }
  46. function 对象字节数(结构对象){
  47.         let 对象数据字节数=0;
  48.         for (let 属性名 in 结构对象) {
  49.                 if (结构对象.hasOwnProperty(属性名)) {
  50.                         对象数据字节数+=结构对象[属性名][0];        //累加字节数
  51.                 }
  52.         }
  53.         return 对象数据字节数;
  54. }
  55. function 结构对象填入数组缓冲(数组缓冲,偏移,结构对象){
  56.         const 数据操作=new DataView(数组缓冲);
  57.         let 字节数,待填数据;
  58.         for (let 属性名 in 结构对象) {
  59.                 if (结构对象.hasOwnProperty(属性名)) {
  60.                         字节数=结构对象[属性名][0],待填数据=结构对象[属性名][1];
  61.                         if(字节数==4){数据操作.setInt32(偏移,待填数据,true);}        //小端序
  62.                         else{if(字节数==2){数据操作.setInt32(偏移,待填数据,true);}
  63.                         else{if(字节数==1){数据操作.setInt32(偏移,待填数据,true);}}}
  64.                         偏移+=字节数;
  65.                 }
  66.         }
  67. }
  68. function 操作鼠标(操作数组){
  69.         let 操作组数=操作数组.length;
  70.         let 结构字节数=对象字节数(操作数组[0]);        /*****计算结构对象字节数*****/
  71.         let 总字节=结构字节数*操作组数;
  72.         const 数组缓冲=new ArrayBuffer(总字节);        //操作对象数组写入缓冲
  73.         for(let i=0;i<操作组数;i++){
  74.                 结构对象填入数组缓冲(数组缓冲,i*结构字节数,操作数组[i]);        /*****对象转数组缓冲*****/
  75.         }
  76.         const 执行宏调用=ExecuteExcel4Macro;        //申请内存
  77.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${总字节},${0x3000},4)`);
  78.         数据写入内存(内存地址,数组缓冲,总字节);        /*****写入鼠标操作结构*****/        //执行鼠标操作
  79.         鼠标操作结果=执行宏调用(`CALL("User32","SendInput","JJJJ",${操作组数},${内存地址},${结构字节数})`);
  80.         if(!鼠标操作结果){console.log("错误代码:"+执行宏调用(`CALL("Kernel32","GetLastError","I")`));}
  81.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  82. }
  83. function 数据写入内存(内存地址,数组缓冲,字节数){
  84.         const 数据操作=new DataView(数组缓冲);
  85.         let 偏移=i=0,待写数据=[],写入字节=[];
  86.         while(字节数>偏移){
  87.                 if(字节数-偏移>=4){待写数据[i]=数据操作.getInt32(偏移,true);写入字节[i]=4;i++;偏移+=4;}
  88.                 else{if(字节数-偏移>=2){待写数据[i]=数据操作.getInt16(偏移,true);写入字节[i]=2;i++;偏移+=2;}
  89.                 else{if(字节数-偏移==1){待写数据[i]=数据操作.getInt8(偏移,true);写入字节[i]=1;i++;偏移++;}}}
  90.         }
  91.         const 执行宏调用=ExecuteExcel4Macro;
  92.         for(偏移=i=0;i<写入字节.length;i++){        //写入
  93.                 执行宏调用(`CALL("Kernel32","RtlMoveMemory","2JNJ",${内存地址+偏移},${待写数据[i]},${写入字节[i]})`);
  94.                 偏移+=写入字节[i];
  95.         }
  96. }
复制代码

数据结构类似鼠标操作。

发表于 2 小时前 | 显示全部楼层
谢谢分享坐个沙发
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层
很复杂的代码,表示看不懂,惭愧
回复

使用道具 举报

 楼主| 发表于 2 小时前 | 显示全部楼层

用WinAPI寻找窗口,并模拟键盘输入

本帖最后由 cutebe 于 2026-4-26 19:02 编辑

测试及调用函数:
  1. function 找到窗口键盘输入测试(){        //记事本编辑框中输入内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.        
  5.         let 记事本类="Notepad";        //找到那个打开的记事本窗口
  6.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  7.         console.log("记事本句柄:"+记事本句柄);
  8.         执行宏调用(`CALL("User32","ShowWindow","JJJ",${记事本句柄},9)`);        //激活并显示SW_RESTORE=9
  9.     执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置
  10.        
  11.         //'A'=0x41, 'B'=0x42, 'C'=0x43, 'N'=0x4E, 'Z'=0x5A
  12.         let 字符串="WuYou.Net";        //无忧论坛网址,用来填写
  13.         let 字符数组=字符串.split(''),按键数组=[];
  14.         for(let i=0;i<字符串.length;i++){
  15.                 var 字符=字符数组[i];
  16.                 if(字符>='a' && 字符<='z'){字符=字符.toUpperCase();}
  17.                 按键数组[i]=键盘操作对象(字符);
  18.         }
  19.         操作键盘(按键数组);        /*****键盘操作*****/
  20. }

  21. function 操作键盘(操作数组){
  22.         let 序号=0,键盘数组=[];
  23.         if(Array.isArray(操作数组)){
  24.                 for(let i=0;i<操作数组.length;i++){
  25.                         if(Array.isArray(操作数组[i])){
  26.                                 for(let j=0;j<操作数组[i].length;j++){
  27.                                         键盘数组[序号]=操作数组[i][j];序号++;
  28.                                 }
  29.                         }else{键盘数组[序号]=操作数组[i];序号++;}
  30.                 }
  31.         }else{键盘数组[序号]=操作数组;}
  32.         let 操作组数=键盘数组.length;
  33.         let 结构字节数=对象字节数(键盘数组[0]);        /*****计算结构对象字节数*****/
  34.         let 总字节=结构字节数*操作组数;
  35.        
  36.         const 数组缓冲=new ArrayBuffer(总字节);        //操作对象数组写入缓冲
  37.         for(let i=0;i<操作组数;i++){
  38.                 结构对象填入数组缓冲(数组缓冲,i*结构字节数,键盘数组[i]);        /*****对象转数组缓冲*****/
  39.         }
  40.         const 执行宏调用=ExecuteExcel4Macro;        //申请内存
  41.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${总字节},${0x3000},4)`);
  42.         数据写入内存(内存地址,数组缓冲,总字节);        /*****写入键盘操作结构*****/        //执行键盘操作
  43.         键盘操作结果=执行宏调用(`CALL("User32","SendInput","JJJJ",${操作组数},${内存地址},${结构字节数})`);
  44.         if(!键盘操作结果){console.log("错误代码:"+执行宏调用(`CALL("Kernel32","GetLastError","I")`));}
  45.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  46. }
  47. function 键盘操作对象(键码){
  48.         class 键盘操作 {        //类
  49.                 constructor(按键,动作){        //类的构造方法,用于构造属性
  50.                         this.输入类型1 = [4,1],        //键盘1        //字节数,数据
  51.                         this.虚拟键码2 = [4,按键],        //同ASCII码
  52.                         this.键扫描码3 = [4,0],
  53.                         this.输入操作4 = [4,动作],        //按键弹起2        启用扫描码8
  54.                         this.时间戳值5 = [4,0],        //系统确定
  55.                         this.扩展信息6 = [4,0],
  56.                         this.数据填充0 = [4,0]        //都是4*7=28字节,不足部分补足
  57.                 }
  58.         };
  59.         if(键码>='A'&&键码<='Z'){键码=键码.charCodeAt(0);}
  60.         if(键码=='.'){键码=0xBE;}
  61.         let 键盘对象 = new 键盘操作(键码,4|2);        //统一码0x4|2键弹起
  62.         return 键盘对象;
  63. }
  64. function 对象字节数(结构对象){
  65.         let 对象数据字节数=0;
  66.         for (let 属性名 in 结构对象) {
  67.                 if (结构对象.hasOwnProperty(属性名)) {
  68.                         对象数据字节数+=结构对象[属性名][0];        //累加字节数
  69.                 }
  70.         }
  71.         return 对象数据字节数;
  72. }
  73. function 结构对象填入数组缓冲(数组缓冲,偏移,结构对象){
  74.         const 数据操作=new DataView(数组缓冲);
  75.         let 字节数,待填数据;
  76.         for (let 属性名 in 结构对象) {
  77.                 if (结构对象.hasOwnProperty(属性名)) {
  78.                         字节数=结构对象[属性名][0],待填数据=结构对象[属性名][1];
  79.                         if(字节数==4){数据操作.setInt32(偏移,待填数据,true);}        //小端序
  80.                         else{if(字节数==2){数据操作.setInt32(偏移,待填数据,true);}
  81.                         else{if(字节数==1){数据操作.setInt32(偏移,待填数据,true);}}}
  82.                         偏移+=字节数;
  83.                 }
  84.         }
  85. }
  86. function 数据写入内存(内存地址,数组缓冲,字节数){
  87.         const 数据操作=new DataView(数组缓冲);
  88.         let 偏移=i=0,待写数据=[],写入字节=[];
  89.         while(字节数>偏移){
  90.                 if(字节数-偏移>=4){待写数据[i]=数据操作.getInt32(偏移,true);写入字节[i]=4;i++;偏移+=4;}
  91.                 else{if(字节数-偏移>=2){待写数据[i]=数据操作.getInt16(偏移,true);写入字节[i]=2;i++;偏移+=2;}
  92.                 else{if(字节数-偏移==1){待写数据[i]=数据操作.getInt8(偏移,true);写入字节[i]=1;i++;偏移++;}}}
  93.         }
  94.         const 执行宏调用=ExecuteExcel4Macro;
  95.         for(偏移=i=0;i<写入字节.length;i++){        //写入
  96.                 执行宏调用(`CALL("Kernel32","RtlMoveMemory","2JNJ",${内存地址+偏移},${待写数据[i]},${写入字节[i]})`);
  97.                 偏移+=写入字节[i];
  98.         }
  99. }
复制代码


回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-4-26 20:45

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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