找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 1012|回复: 8

[转载代码] 在办公软件WPS的JSA中模拟键盘输入

[复制链接]
发表于 2026-4-26 23:12:03 | 显示全部楼层 |阅读模式
办公软件WPS的表格:通过ExecuteExcel4Macro调用WinAPI实现

测试与调用函数:        //打开记事本,输入内容
  1. function 找到记事本窗口键盘输入测试(){        //记事本编辑框中输入内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.        
  5.         let 记事本类="Notepad";        //找到那个打开的记事本窗口
  6.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  7.         console.log("记事本句柄:"+记事本句柄);
  8.         if(!记事本句柄){
  9.                 let 记事本进程句柄=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFJJJ",0,"open","notepad",0,0,1)`);
  10.                 console.log("记事本进程句柄:"+记事本进程句柄);
  11.                 alert("等待,确定后向记事本写入信息");
  12.                 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  13.                 console.log("记事本句柄:"+记事本句柄);
  14.         }
  15.     执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置
  16.        
  17.         let 字符串="BatHome.Net";        //批处理之家论坛网址,作为填写内容
  18.         let 字符数组=字符串.split(''),按键数组=[];
  19.         for(let i=0;i<字符串.length;i++){
  20.                 var 字符=字符数组[i];
  21.                 if(字符>='a' && 字符<='z'){字符=字符.toUpperCase();}
  22.                 按键数组[i]=键盘操作对象(字符);
  23.         }
  24.         操作键盘(按键数组);        /*****键盘操作*****/
  25. }

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

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 感谢分享

查看全部评分

 楼主| 发表于 2026-4-27 11:15:07 | 显示全部楼层
通过SendMessage向文本编辑区填入内容:
  1. function 记事本窗口发送文本测试(){        //记事本编辑框中内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.         
  5.         //找到打开的记事本窗口,没有则打开一个新记事本
  6.         let 记事本类="Notepad";
  7.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  8.         console.log("记事本句柄:"+记事本句柄);
  9.         if(!记事本句柄){
  10.                 let 记事本进程句柄=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFJJJ",0,"open","notepad",0,0,1)`);
  11.                 console.log("记事本进程句柄:"+记事本进程句柄);
  12.                 alert("等待,确定后向记事本写入信息");        //弹窗提示
  13.                 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  14.                 console.log("记事本句柄:"+记事本句柄);
  15.         }
  16.             执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置
  17.         
  18.         //定位到记事本的编辑输入区
  19.         let 编辑框类="Edit";
  20.         let 编辑框句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFJ",${记事本句柄},0,"${编辑框类}",0)`);
  21.         
  22.         //通过发送消息,向记事本写入文本
  23.         let 设置文本=0xC,字符串="BatHome.Net";        //批处理之家论坛网址,作为内容
  24.         var 设置文本框内容=执行宏调用(`CALL("User32", "SendMessageA", "JJJJF", ${编辑框句柄},${设置文本},0,"${字符串}")`);
  25. }
复制代码
 楼主| 发表于 2026-5-3 11:11:31 | 显示全部楼层

模拟键盘输入应用:截屏

截取全屏和当前窗口函数:

  1. function 截取全屏测试(){        //截屏键PrintScreen
  2.         let 按下=0,扩展=1,松开=2;
  3.         let 截屏键码=0x2C,截屏扫描码=0x37;
  4.         键盘事件(截屏键码,截屏扫描码,按下|扩展);        //按下PrintScreen
  5.         键盘事件(截屏键码,截屏扫描码,松开|扩展);        //松开PrintScreen
  6. }
  7. function 截屏当前窗口测试(){        //当前窗口 Alt + PrintScreen
  8.         let 按下=0,扩展=1,松开=2;        //Alt0x12,左Alt0xA4
  9.         let 修改键码=0x12,截屏键码=0x2C,截屏扫描码=0x37;
  10.         键盘事件(修改键码,0,按下);        //按下Alt
  11.         键盘事件(截屏键码,截屏扫描码,按下|扩展);        //按下PrintScreen
  12.         键盘事件(截屏键码,截屏扫描码,松开|扩展);        //松开PrintScreen
  13.         键盘事件(修改键码,0,松开);        //松开Alt
  14. }
  15. function 键盘事件(虚拟键码,扫描键码,键标志){
  16.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  17.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  18. }
复制代码
 楼主| 发表于 2026-5-3 11:16:52 | 显示全部楼层

模拟键盘输入应用:打开运行对话框

打开运行对话框:Win + R
  1. function 打开运行对话框键盘测试(){        //快捷键 Win + R
  2.         let 按下=0,扩展=1,松开=2;
  3.         //键盘事件(虚拟键码,扫描键码,键标志);
  4.         let 左窗口=0x5B,运行=0x52;
  5.         键盘事件(左窗口,左窗口,按下|扩展);        //按下LWin
  6.         键盘事件(运行,0,按下);        //按下R
  7.         键盘事件(运行,0,松开);        //松开R
  8.         键盘事件(左窗口,左窗口,松开|扩展);        //松开LWin        //合成 LWin + R 运行
  9. }
  10. function 键盘事件(虚拟键码,扫描键码,键标志){
  11.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  12.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  13. }
复制代码
 楼主| 发表于 2026-5-3 11:19:36 | 显示全部楼层

模拟键盘输入应用:打开/关闭小键盘数字指示灯

  1. function 关闭数字灯(){
  2.         let 数字键码=0x90;
  3.         let 数字灯状态=获取按键状态(数字键码);        //关闭0
  4.         if(数字灯状态){
  5.                 let 数字扫描码=0x45,按下=0,扩展=1,松开=2;
  6.                 键盘事件(数字键码,数字扫描码,按下|扩展);        //按下NumLock
  7.                 键盘事件(数字键码,数字扫描码,松开|扩展);        //松开NumLock
  8.         }
  9. }
  10. function 打开数字灯(){
  11.         let 数字键码=0x90;
  12.         let 数字灯状态=获取按键状态(数字键码);        //打开1
  13.         if(!数字灯状态){
  14.                 let 数字扫描码=0x45,按下=0,扩展=1,松开=2;
  15.                 键盘事件(数字键码,数字扫描码,按下|扩展);        //按下NumLock
  16.                 键盘事件(数字键码,数字扫描码,松开|扩展);        //松开NumLock
  17.         }
  18. }
  19. function 获取按键状态(键盘码){
  20.         const 执行宏调用=ExecuteExcel4Macro;
  21.         let 状态=执行宏调用(`CALL("User32","GetKeyState","IJ",${键盘码})`);
  22.         return 状态;
  23. }
  24. function 键盘事件(虚拟键码,扫描键码,键标志){
  25.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  26.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  27. }
复制代码
 楼主| 发表于 2026-5-3 11:58:52 | 显示全部楼层
本帖最后由 cutebe 于 2026-5-3 12:00 编辑
  1. function 显示桌面键盘测试(){        //快捷键 Win + D
  2.         let 按下=0,扩展=1,松开=2;
  3.         let 左窗口=0x5B,按键D='D'.charCodeAt();
  4.         键盘事件(左窗口,左窗口,按下|扩展);        //按下LWin
  5.         键盘事件(按键D,0,按下);        //按下D
  6.         键盘事件(按键D,0,松开);        //松开D
  7.         键盘事件(左窗口,左窗口,松开|扩展);        //松开LWin        //合成 LWin + D
  8. }
  9. function 键盘事件(虚拟键码,扫描键码,键标志){
  10.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  11.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  12. }
复制代码


扩展按键虚拟键码扫描码说明
----- --------------------
系统关机0xE05E
系统睡眠0xE05F
系统唤醒0xE063
键盘 PrintScreen 键0x2C0xE037
键盘 Pause 键0x130xE046
键盘 Insert 键0x2D0xE052
键盘 Home 键0x240xE047
键盘 PageUp 键0x210xE049
键盘 Delete 键0x2E0xE053
键盘 End 键0x230xE04F
键盘 PageDown 键0x220xE051
键盘向右→键0x270xE04D
键盘向左←键0x250xE04B
键盘向下↓键0x280xE050
键盘向上↑键0x260xE048
小键盘 Num Lock 键0x900xE045
小键盘 /0x6F0xE035
小键盘 ENTER 键0xE01C
键盘应用程序键0x5D0xE05D菜单键VK_APPS,在右Win和右Ctrl之间
键盘电源键0xE05E
键盘 左Win 键0x5B0xE05B
键盘 右Ctrl 键0xA30xE01DVK_RCONTROL
键盘 右Alt 键0xA50xE038VK_RMENU
键盘 右Win 键0x5C0xE05C
扫描下一个曲目0xE019
扫描上一个曲目0xE010
停止0xE024
播放/暂停0xE022
静音0xE020
音量增大0xE030
音量减小0xE02E
AL 使用者控制配置0xE06D
AL 电子邮件阅读器0xE06C
AL 计算器0xE021
AL 本地计算机浏览器0xE06B
AC 搜索0xE065
AC 主页0xE032
AC 返回0xE06A
AC 向前0xE069
AC 停止0xE068
AC 刷新0xE067
AC 书签0xE066
 楼主| 发表于 2026-5-3 23:40:55 | 显示全部楼层

模拟键盘输入测试:内码转文字

  1. function 文字模拟数字按键输入测试(){
  2.         let 我=52946,爱=45230,你=50403;
  3.         let C=0x43,N=0x4E;
  4.         let 输出字符串=[我,爱,你,C,N];
  5.         for(let i=0;i<输出字符串.length;i++){
  6.                 组合数码键入对应文字(输出字符串[i]);
  7.         }
  8.         //光标放在此处:
  9. }
  10. function 组合数码键入对应文字(数字码){        //数字码为内码
  11.         let 数字串=数字码.toString();        //转数字字符串
  12.         let 按下=0,松开=2,长修码=0x12;
  13.         键盘事件(长修码,0,按下);        //按下键Alt
  14.         for(let i=0;i<数字串.length;i++){
  15.                 let 数字=数字串[i];
  16.                 let 小键盘数字码=0x30+数字.charCodeAt(0);
  17.                 let 小键盘数字扫描码=按键码转扫描码(小键盘数字码);
  18.                 键盘事件(小键盘数字码,小键盘数字扫描码,按下);
  19.                 键盘事件(小键盘数字码,小键盘数字扫描码,松开);
  20.         }
  21.         键盘事件(长修码,0,松开);        //松开键Alt
  22. }
  23. function 键盘事件(虚拟键码,扫描键码,键标志){
  24.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键小键盘数字会用到扫描码
  25.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  26. }
  27. function 按键码转扫描码(按键码){        //返回扫描码
  28.         const 执行宏调用=ExecuteExcel4Macro;
  29.         let 扫描码=执行宏调用(`CALL("User32","MapVirtualKeyA","JJJ",${按键码},0)`);
  30.         return 扫描码;
  31. }
复制代码
 楼主| 发表于 2026-5-4 16:59:21 | 显示全部楼层

模拟键盘输入文字:Alt + 内码

批处理:Alt+50682,Alt+46246,Alt+49389

  1. function 记事本窗口模拟键盘输入文本测试(){        //记事本编辑框中内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.        
  5.         //找到打开的记事本窗口,没有则打开一个新记事本
  6.         let 记事本类="Notepad";
  7.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  8.         console.log("记事本句柄:"+记事本句柄);
  9.         if(!记事本句柄){
  10.                 let 记事本进程句柄=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFJJJ",0,"open","notepad",0,0,1)`);
  11.                 console.log("记事本进程句柄:"+记事本进程句柄);
  12.                 alert("等待,确定后向记事本写入信息");        //弹窗提示
  13.                 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  14.                 console.log("记事本句柄:"+记事本句柄);
  15.         }
  16.        
  17.         //字符串写入内存,再按数据方式读取出来(即内码)
  18.         字符串="批处理之家 BatHome.Net";
  19.         let 内存句柄=字符串到内存(字符串);        //===写字符串===//
  20.         let 读出字符串=内存取字符串(内存句柄);
  21.         console.log(读出字符串);
  22.         let 数据数组缓冲=内存取数据(内存句柄);        //===读取数据===//
  23.         显示数组缓冲(数据数组缓冲);        //===显示数据===//
  24.         执行宏调用(`CALL("Kernel32","GlobalFree","JJ",${内存句柄})`);        //释放内存
  25.         let 文字内码=数组缓冲转文字内码数组(数据数组缓冲);
  26.         console.log("文字内码数组:"+文字内码);
  27.        
  28.         //模拟键盘按键,向记事本写入文本
  29.         执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置记事本窗口
  30.         for(let i=0;i<文字内码.length;i++){
  31.                 组合数码键入对应文字(文字内码[i]);
  32.         }        //光标放在此处:
  33. }

  34. function 数组缓冲转文字内码数组(数组缓冲){        //返回数组
  35.         const 总字节=数组缓冲.byteLength;
  36.         const 数据操作=new DataView(数组缓冲);
  37.         let 偏移=0,文字内码=[];
  38.         while(偏移<总字节){
  39.                 var 文字数码=数据操作.getUint8(偏移,true),偏移增量=1;
  40.                 if(!文字数码){break;}
  41.                 else{if(文字数码>0x80){文字数码=数据操作.getUint16(偏移),偏移增量=2;}}
  42.                 文字内码.push(文字数码);
  43.                 偏移+=偏移增量;
  44.         }
  45.         return 文字内码;
  46. }
  47. function 组合数码键入对应文字(数字码){        //数字码为内码
  48.         let 数字串=数字码.toString();        //转数字字符串
  49.         let 按下=0,松开=2,长修码=0x12;
  50.         键盘事件(长修码,0,按下);        //按下键Alt
  51.         for(let i=0;i<数字串.length;i++){
  52.                 let 数字=数字串[i];
  53.                 let 小键盘数字码=0x30+数字.charCodeAt(0);
  54.                 let 小键盘数字扫描码=按键码转扫描码(小键盘数字码);
  55.                 键盘事件(小键盘数字码,小键盘数字扫描码,按下);
  56.                 键盘事件(小键盘数字码,小键盘数字扫描码,松开);
  57.         }
  58.         键盘事件(长修码,0,松开);        //松开键Alt
  59. }
  60. function 键盘事件(虚拟键码,扫描键码,键标志){
  61.         const 执行宏调用=ExecuteExcel4Macro;        //扩展时扫描码只需要低位,高位0xE0省略        //扩展键小键盘数字会用到扫描码
  62.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  63. }
  64. function 按键码转扫描码(按键码){        //返回扫描码
  65.         const 执行宏调用=ExecuteExcel4Macro;
  66.         let 扫描码=执行宏调用(`CALL("User32","MapVirtualKeyA","JJJ",${按键码},0)`);
  67.         return 扫描码;
  68. }
  69. function 字符串到内存(字符串){        //返回内存句柄
  70.         const 执行宏调用=ExecuteExcel4Macro;
  71.         let 分段文本=[],分段字节=[],总字节=0,段长度=127;        //可申请256字节内存,结束符1字节,汉字最长127
  72.         for(let 起始=i=0;起始<字符串.length;起始+=段长度,i++){
  73.                 分段文本.push(字符串.slice(起始,起始+段长度));
  74.                 分段字节.push(分段文本[i].replace(/[^\x00-\xff]/g,'xx').length);        //一个汉字占两个字节
  75.                 总字节+=分段字节[i];
  76.         }        //分配内存        //分配GlobalAlloc对应销毁GlobalFree        //分配GlobalAlloc对应销毁GlobalFree
  77.         const 内存句柄=执行宏调用(`CALL("Kernel32","GlobalAlloc","JJJ",${0x42},${总字节+1})`);
  78.         if(内存句柄){        //内存分配成功,然后锁写解内存。        //锁定全局内存对象,会返回其内存地址
  79.                 const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
  80.                 for(let 偏移字节=i=0;i<分段文本.length;i++){        //字符串(JS变量)分批复制到刚申请的内存中。分批是因为有限长
  81.                         执行宏调用(`CALL("Kernel32","lstrcpynW","JJFJ",${内存地址+偏移字节},"${分段文本[i].replace(/\"/g,'\"\"')}",${分段字节[i]})`);
  82.                         偏移字节+=分段字节[i];        //返回地址J。        //字符串两个双引号解释成一个
  83.                 }
  84.                 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);        //解锁全局内存对象,以释放资源
  85.                 return 内存句柄;
  86.         }else{console.log("未能分配内存!");}
  87. }
  88. function 内存取字符串(内存句柄){        //返回字符串
  89.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  90.         const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);        //锁定,获取内存地址
  91.         if(内存地址){
  92.                 const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  93.                 let 偏移字节=0,文本字符串=分段文本='';
  94.                 while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  95.                         分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  96.                         //偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  97.                         偏移字节+=执行宏调用(`LENB("${分段文本.replace(/"/g,'x')}")`);
  98.                         文本字符串+=分段文本;
  99.                 }        //解锁全局内存对象,以释放资源
  100.                 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);
  101.                 return 文本字符串;
  102.         }else{console.log("未找到内存地址!");}
  103. }
  104. function 内存取数据(内存句柄){        //返回数组缓冲
  105.         const 执行宏调用=ExecuteExcel4Macro;
  106.         const 总字节=执行宏调用(`CALL("Kernel32","GlobalSize","JJ",${内存句柄})`);        //内存对象空间大小
  107.         let 偏移,i,读取字节=[],读出数据;
  108.         for(偏移=i=0;偏移<总字节;i++){
  109.                 if(总字节-偏移>=4){读取字节[i]=4;偏移+=4;}
  110.                 else{if(总字节-偏移>=2){读取字节[i]=2;偏移+=2;}
  111.                 else{if(总字节-偏移==1){读取字节[i]=1;偏移++;}}}
  112.         }
  113.         const 数组缓冲=new ArrayBuffer(总字节);        //用于存储读出的数据
  114.         const 数据操作=new DataView(数组缓冲);
  115.         const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
  116.         if(内存地址){        //var 文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址},${127})`);
  117.                 for(偏移=i=0;偏移<总字节;i++){        //库Kernel32.dll和NtDll.dll里都有RtlMoveMemory
  118.                         读出数据=执行宏调用(`CALL("Kernel32","RtlMoveMemory","1NJJ",${内存地址},${内存地址+偏移},${读取字节[i]})`);        //读出
  119.                         if(读取字节[i]==4){数据操作.setInt32(偏移,读出数据,true);偏移+=4;}
  120.                         else{if(读取字节[i]==2){数据操作.setInt16(偏移,读出数据,true);偏移+=2;}
  121.                         else{if(读取字节[i]==1){数据操作.setInt8(偏移,读出数据,true);偏移++;}}}
  122.                 }
  123.                 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);        //解锁内存对象,以释放资源
  124.                 return 数组缓冲;        //返回
  125.         }else{console.log("未找到内存地址!");}
  126. }
  127. function 显示数组缓冲(数组缓冲){
  128.         const 数据操作=new DataView(数组缓冲);
  129.         var 字节数码串=[],字符串=[],行号,四分隔,八分隔;
  130.         for(let 偏移=0;偏移<数组缓冲.byteLength;偏移++){
  131.                 var 字节数码=数据操作.getInt8(偏移);
  132.                 行号=Math.floor(偏移/16);
  133.                 if((偏移+1)%4){四分隔=''}else{四分隔=' '};
  134.                 if((偏移+1)%8){八分隔=''}else{八分隔=' '};
  135.                 if(typeof 字节数码串[行号]=="undefined"){字节数码串[行号]=''}
  136.                 var 字节高位=(字节数码>>>4&0xF).toString(16).toUpperCase(),字节低位=(字节数码&0xF).toString(16).toUpperCase();
  137.                 字节数码串[行号]+=字节高位+字节低位+" "+四分隔+八分隔;
  138.                 if(typeof 字符串[行号]=="undefined"){字符串[行号]=''}
  139.                 if(字节数码){字符串[行号]+=String.fromCharCode(字节数码);}else{字符串[行号]+=' ';}
  140.         }
  141.         for(let 行号=0;行号<字节数码串.length;行号++){
  142.                 var 十六进制行号=('000'+(行号<<4).toString(16)).slice(-4).toUpperCase();
  143.                 console.log(十六进制行号+":"+字节数码串[行号]+"\t["+字符串[行号]+"]");
  144.         }
  145. }
复制代码
 楼主| 发表于 5 小时前 | 显示全部楼层

找到窗口,模拟键盘输入数字编码

  1. function 超量多码(){
  2.         console.clear();
  3.         var 剪贴板文本=获取剪贴板文本();        //编辑取自剪贴板
  4.         var 数字串=剪贴板文本.replace(/[^\d^,]+/g,',');        //非数字替换成分隔符
  5.         var 数串数组=数字串.split(','),除重对象={},数码="",计数=0;        //数组:六位除重
  6.         for(var 序号=0;序号<数串数组.length;序号++){
  7.                 if(数串数组[序号].length==6 && typeof 除重对象[数串数组[序号]]=='undefined'){
  8.                         除重对象[数串数组[序号]]=1;计数++;数码+=数串数组[序号]+',';
  9.                 }
  10.         }
  11.         console.log("编码:"+数码);        //数码即编码数组。
  12.         if(数码=='' || 数码==','){alert("编码为空!退出……");return;}        //空串,即没有编码
  13.        
  14.         let 标题="多品种商品选择",类="FNWNS3100";
  15.         let 选择窗口句柄=查找窗口(标题,类);
  16.         if(!选择窗口句柄){alert("未找到超量多码输入窗口,退出!");return;}
  17.        
  18.         let 自身窗口句柄=获取活动窗口句柄();        //最小化自身,方便输入编码
  19.         窗口最小化(自身窗口句柄);
  20.         前置窗口(选择窗口句柄);延时(300);

  21.         let 添加按钮标题='添加(&A)',按钮类='Button';
  22.         let 添加按钮句柄=下一个子窗口(选择窗口句柄,0,添加按钮标题,0);
  23.         let 按钮范围=获取窗口范围(添加按钮句柄);
  24.         var 按钮水平=按钮范围[0],按钮垂直=按钮范围[1];
  25.        
  26.         let 编码框中水平=按钮水平-136,编码框中垂直=按钮垂直+12;        //添加按钮相对编码框距离
  27.         设置鼠标位置(编码框中水平,编码框中垂直);
  28.         鼠标点击();        //光标定位编码框中
  29.        
  30.         let 编码组=数码.split(',');
  31.         for(let i=0;i<编码组.length;i++){
  32.                 if(编码组[i]!=""){
  33.                         模拟键盘输入编码(编码组[i]);        //输入编码
  34.                         模拟键盘回车();        //回车确定
  35.                         延时(800);        //处理弹出对话框或窗口:一、已存在;二、错误;三、不全需要选择。
  36.                         let 错误对话框句柄=查找对话框窗口("错误");        //输入编码不存在
  37.                         if(错误对话框句柄){延时(200);
  38.                                 let 确定按钮=下一个子窗口(错误对话框句柄,0,"确定",0);
  39.                                 发送点击按钮消息(确定按钮);
  40.                         }
  41.                         let 提示对话框句柄=查找对话框窗口("提示");        //重复,编码已在列表中
  42.                         if(提示对话框句柄){延时(200);
  43.                                 let 确定按钮=下一个子窗口(提示对话框句柄,0,"确定",0);
  44.                                 发送点击按钮消息(确定按钮);
  45.                         }        //还有一个列表选择窗未处理
  46.                 }
  47.         }
  48.         延时(300);        //恢复窗口显示
  49.         let 恢复结果=恢复窗口(自身窗口句柄);
  50. }

  51. function 获取剪贴板文本(){        //返回字符串
  52.         let 内存地址,剪贴板文本="",执行宏调用=ExecuteExcel4Macro;
  53.         if(执行宏调用(`CALL("user32.dll","OpenClipboard","JJ",0)`)){        //打开剪贴板
  54.                 const 内存句柄=执行宏调用(`CALL("user32.dll","GetClipboardData","JJ",1)`);        //获取剪贴板文本,返回句柄。
  55.                 if(内存句柄){        //锁定全局内存对象,获取内存地址
  56.                         内存地址=执行宏调用(`CALL("kernel32.dll","GlobalLock","JJ",${内存句柄})`);
  57.                         let 总字节,偏移字节=0,段长度=127,分段文本='';
  58.                         总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //剪贴板文本字节数
  59.                         while(偏移字节<总字节){        //返回字符串F。返回值超255字节时,也需要分段操作
  60.                                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  61.                                 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算分段文本字节数
  62.                                 剪贴板文本+=分段文本;
  63.                         }
  64.                         执行宏调用(`CALL("kernel32.dll","GlobalUnlock","JJ",${内存句柄})`);        //解锁
  65.                 }else{console.log("未能获取剪贴板数据的内存句柄!");}
  66.                 执行宏调用(`CALL("user32.dll","CloseClipboard","J")`);        //关闭剪贴板,让其它应用可以使用剪贴板
  67.                 return 剪贴板文本;        //返回字符串
  68.         }else{alert('无法打开剪贴板!');}
  69. }

  70. function 查找窗口(标题,类){        //返回句柄
  71.         const 执行宏调用=ExecuteExcel4Macro;
  72.         var 窗口句柄;
  73.         if(!标题){        //标题为0               
  74.                 if(!类){        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JJJ",0,0)`);        //类为0
  75.                 }else{        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${类}",0)`);}
  76.         }else{
  77.                 if(!类){        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JJF",0,"${标题}")`);        //类为0
  78.                 }else{        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JFF","${类}","${标题}")`);}
  79.         }
  80.         return 窗口句柄;
  81. }

  82. function 获取活动窗口句柄(){        //进程所在自身窗口
  83.         const 执行宏调用=ExecuteExcel4Macro;
  84.         let 自身窗口句柄=执行宏调用(`CALL("User32","GetActiveWindow","J")`);
  85.         return 自身窗口句柄;
  86. }

  87. function 前置窗口(窗口句柄){
  88.         const 执行宏调用=ExecuteExcel4Macro;
  89.         let 前置结果=执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${窗口句柄})`);
  90.         return 前置结果;
  91. }

  92. function 窗口最小化(窗口句柄){let 激活最小化=2;return 显示窗口(窗口句柄,激活最小化);}
  93. function 恢复窗口(窗口句柄){let 恢复=9;return 显示窗口(窗口句柄,恢复);}
  94. function 显示窗口(窗口句柄,显示标识){        //普通显示=1,显示=5,激活最小化=2,最小化=6,恢复=9;
  95.         const 执行宏调用=ExecuteExcel4Macro;
  96.         let 显示结果=执行宏调用(`CALL("User32","ShowWindow","AJJ",${窗口句柄},${显示标识})`);
  97.         return 显示结果;
  98. }

  99. function 延时(毫秒数){
  100.         const 执行宏调用=ExecuteExcel4Macro;
  101.         执行宏调用(`CALL("Kernel32","Sleep","JJ",${毫秒数})`);
  102. }

  103. function 下一个子窗口(父句柄,上个子句柄,标题,类){
  104.         const 执行宏调用=ExecuteExcel4Macro;
  105.         var 子句柄;
  106.         if(!标题){        //标题为0               
  107.                 if(!类){        子句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJJJ",${父句柄},${上个子句柄},0,0)`);        //类为0
  108.                 }else{        子句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFJ",${父句柄},${上个子句柄},"${类}",0)`);}
  109.         }else{
  110.                 if(!类){        子句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJJF",${父句柄},${上个子句柄},0,"${标题}")`);        //类为0
  111.                 }else{        子句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFF",${父句柄},${上个子句柄},"${类}","${标题}")`);}
  112.         }
  113.         return 子句柄;
  114. }

  115. function 获取窗口范围(窗口句柄){        //返回坐标数组:左上右下
  116.         const 执行宏调用=ExecuteExcel4Macro;
  117.         let 内存地址=申请虚拟内存(16);        //===申请内存===//
  118.         let 结果=执行宏调用(`CALL("User32","GetWindowRect","JJJ",${窗口句柄},${内存地址})`);
  119.         let 数组缓冲=内存读取数据(内存地址,16);        //===读取数据===/
  120.         释放虚拟内存(内存地址);        //===释放内存===//
  121.         let 坐标数组=缓冲转数组(数组缓冲);        //===转数组===//
  122.         return 坐标数组;
  123. }

  124. function 申请虚拟内存(字节数){        //返回内存地址
  125.         const 执行宏调用=ExecuteExcel4Macro;
  126.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${字节数},${0x3000},4)`);
  127.         return 内存地址;
  128. }

  129. function 释放虚拟内存(内存地址){
  130.         const 执行宏调用=ExecuteExcel4Macro;
  131.         执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);
  132. }

  133. function 内存读取数据(内存地址,字节数){        //返回数组缓冲
  134.         const 执行宏调用=ExecuteExcel4Macro;
  135.         let 偏移,i,读取字节=[],读出数据;
  136.         for(偏移=i=0;偏移<字节数;i++){
  137.                 if(字节数-偏移>=4){读取字节[i]=4;偏移+=4;}
  138.                 else{if(字节数-偏移>=2){读取字节[i]=2;偏移+=2;}
  139.                 else{if(字节数-偏移==1){读取字节[i]=1;偏移++;}}}
  140.         }
  141.         const 数组缓冲=new ArrayBuffer(字节数);        //用于存储读出的数据
  142.         const 数据操作=new DataView(数组缓冲);
  143.         for(偏移=i=0;偏移<字节数;i++){        //库Kernel32.dll和NtDll.dll里都有RtlMoveMemory        //读出
  144.                 读出数据=执行宏调用(`CALL("Kernel32","RtlMoveMemory","1NJJ",${内存地址},${内存地址+偏移},${读取字节[i]})`);
  145.                 if(读取字节[i]==4){数据操作.setInt32(偏移,读出数据,true);偏移+=4;}
  146.                 else{if(读取字节[i]==2){数据操作.setInt16(偏移,读出数据,true);偏移+=2;}
  147.                 else{if(读取字节[i]==1){数据操作.setInt8(偏移,读出数据,true);偏移++;}}}
  148.         }
  149.         return 数组缓冲;        //返回
  150. }

  151. function 缓冲转数组(数组缓冲){        //返回数组[]
  152.         let 总字节=数组缓冲.byteLength;
  153.         let 组数=Math.ceil(总字节/4);
  154.         const 数据操作=new DataView(数组缓冲);
  155.         let 数组=[];
  156.         for(let i=0;i<组数;i++){
  157.                 数组[i]=数据操作.getInt32(i*4,true);
  158.         }
  159.         return 数组;
  160. }

  161. function 设置鼠标位置(水平,垂直){
  162.         const 执行宏调用=ExecuteExcel4Macro;
  163.         var 定位结果=执行宏调用(`CALL("User32","SetCursorPos","AJJ",${水平},${垂直})`);
  164.         return 定位结果;        //成功返回true
  165. }

  166. function 鼠标单击(){鼠标事件(6);}
  167. function 鼠标点击(){鼠标事件(6);}
  168. function 鼠标双击(){鼠标单击();鼠标点击();}
  169. function 鼠标右击(){鼠标事件(0x18);}
  170. function 鼠标事件(动作){
  171.         const 执行宏调用=ExecuteExcel4Macro;
  172.         执行宏调用(`CALL("User32","mouse_event","JJJJJJ",${动作},0,0,0,0)`);
  173. }

  174. function 模拟键盘输入编码(编码串){        //六位数字编码串,可能有0开头的字符串
  175.         for(let i=0;i<编码串.length;i++){
  176.                 let 数字码=编码串[i];
  177.                 小键盘输入单个数字(数字码);
  178.         }
  179. }

  180. function 模拟键盘回车(){let 回车码=0xD;模拟键盘按键(回车码);}
  181. function 模拟键盘按键(按键码){
  182.         let 扫描码=按键码转扫描码(按键码);let 按下=0,松开=2;
  183.         键盘事件(按键码,扫描码,按下);键盘事件(按键码,扫描码,松开);
  184. }

  185. function 小键盘输入单个数字(数字){        //单个数字0~9
  186.         let 小键盘数字码;
  187.         if(typeof 数字=='number'){小键盘数字码=0x60+数字;}else{
  188.         if(typeof 数字=="string"){小键盘数字码=0x30+数字.charCodeAt(0);}}
  189.         let 小键盘数字扫描码=按键码转扫描码(小键盘数字码);
  190.         let 按下=0,松开=2;
  191.         键盘事件(小键盘数字码,小键盘数字扫描码,按下);
  192.         键盘事件(小键盘数字码,小键盘数字扫描码,松开);
  193. }

  194. function 按键码转扫描码(按键码){        //返回扫描码
  195.         const 执行宏调用=ExecuteExcel4Macro;
  196.         let 扫描码=执行宏调用(`CALL("User32","MapVirtualKeyA","JJJ",${按键码},0)`);
  197.         return 扫描码;
  198. }

  199. function 键盘事件(虚拟键码,扫描键码,键标志){
  200.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  201.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  202. }

  203. function 查找对话框窗口(标题){
  204.         var 对话框句柄=查找窗口(标题,"#32770");        //对话框类#32770
  205.         return 对话框句柄;
  206. }

  207. function 发送点击按钮消息(按钮句柄){var 点击=0xF5;发送消息(按钮句柄,点击);}
  208. function 发送关闭窗口消息(窗口句柄){var 关闭=0x10;发送消息(窗口句柄,关闭);}
  209. function 发送消息(窗口句柄,消息){        //等待结果返回
  210.         const 执行宏调用=ExecuteExcel4Macro;
  211.         执行宏调用(`CALL("User32","SendMessageA","JJJJJ",${窗口句柄},${消息},0,0)`);
  212. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-6-12 23:17

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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