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

[原创代码] 在办公软件WPS的JSA中实现获取鼠标指针处窗口标题

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

测试与调用函数:
  1. function 获取鼠标指针处窗口标题测试(){
  2.         const 执行宏调用=ExecuteExcel4Macro;
  3.        
  4.         //鼠标指针坐标
  5.         let 鼠标指针坐标=获取鼠标位置();        /*****获取鼠标指针坐标*****/
  6.         let 水平=鼠标指针坐标[0],垂直=鼠标指针坐标[1];
  7.         console.clear();
  8.         console.log("鼠标当前位置:("+水平+","+垂直+")");
  9.        
  10.         //鼠标指针处窗口句柄        //扩展参数成功,增加了一个参数
  11.         let 窗口句柄=执行宏调用(`CALL("User32", "WindowFromPoint", "JJJ", ${水平},${垂直})`);
  12.         console.log("窗口句柄:"+窗口句柄);
  13.        
  14.         //获取窗口标题长度
  15.         let 窗口标题长度=执行宏调用(`CALL("User32", "GetWindowTextLengthA", "JJ", ${窗口句柄})`);
  16.         console.log("窗口标题长度:"+窗口标题长度);
  17.        
  18.         const 内存地址 = 执行宏调用(`CALL("Kernel32", "VirtualAlloc", "JJJJJ", 0, ${窗口标题长度+1}, ${0x3000}, 4)`);
  19.         //获取窗口标题        //申请内存↑
  20.         let 标题长度=执行宏调用(`CALL("User32", "GetWindowTextA", "JJJJ", ${窗口句柄},${内存地址},${窗口标题长度+1})`);
  21.         let 窗口标题=内存读取字符串(内存地址);        /*****获取内存文本*****/
  22.         console.log("标题长度:"+标题长度+"\n窗口标题:"+窗口标题);
  23.         let 标题数组缓冲=内存读取数据(内存地址,窗口标题长度+1);        /*****读取数据*****/
  24.         显示数组缓冲(标题数组缓冲);        /*****显示数据*****/
  25.        
  26.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  27. }

  28. function 获取鼠标位置(){        //返回坐标数组[x,y]
  29.         const 执行宏调用=ExecuteExcel4Macro;        //逻辑值 GetCursorPos([输出]结构 屏幕坐标指针)
  30.         var 坐标结构=执行宏调用(`CALL("User32","GetCursorPos","1E",0)`);        //参数:4+4字节坐标结构
  31.         const 缓冲区=new ArrayBuffer(8); //8字节对应64位
  32.         const 数据操作=new DataView(缓冲区);        //操作对象
  33.         数据操作.setFloat64(0,坐标结构);        //(操作)写入64位数
  34.         let 坐标=[];
  35.         坐标[0]=数据操作.getInt32(4);        //取32位坐标x
  36.         坐标[1]=数据操作.getInt32(0);        //取32位坐标y
  37.         return 坐标;
  38. }
  39. function 内存读取字符串(内存地址){        //返回字符串
  40.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  41.         const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  42.         let 偏移字节=0,文本字符串=分段文本='';
  43.         while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  44.                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  45.                 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  46.                 文本字符串+=分段文本;
  47.         }
  48.         return 文本字符串;
  49. }
  50. function 内存读取数据(内存地址,字节数){        //返回数组缓冲
  51.         const 执行宏调用=ExecuteExcel4Macro;
  52.         let 偏移,i,读取字节=[],读出数据;
  53.         for(偏移=i=0;偏移<字节数;i++){
  54.                 if(字节数-偏移>=4){读取字节[i]=4;偏移+=4;}
  55.                 else{if(字节数-偏移>=2){读取字节[i]=2;偏移+=2;}
  56.                 else{if(字节数-偏移==1){读取字节[i]=1;偏移++;}}}
  57.         }
  58.         const 数组缓冲=new ArrayBuffer(字节数);        //用于存储读出的数据
  59.         const 数据操作=new DataView(数组缓冲);
  60.         for(偏移=i=0;偏移<字节数;i++){        //库Kernel32.dll和NtDll.dll里都有RtlMoveMemory        //读出
  61.                 读出数据=执行宏调用(`CALL("Kernel32","RtlMoveMemory","1NJJ",${内存地址},${内存地址+偏移},${读取字节[i]})`);
  62.                 if(读取字节[i]==4){数据操作.setInt32(偏移,读出数据,true);偏移+=4;}
  63.                 else{if(读取字节[i]==2){数据操作.setInt16(偏移,读出数据,true);偏移+=2;}
  64.                 else{if(读取字节[i]==1){数据操作.setInt8(偏移,读出数据,true);偏移++;}}}
  65.         }
  66.         return 数组缓冲;        //返回
  67. }
  68. function 显示数组缓冲(数组缓冲){
  69.         const 数据操作=new DataView(数组缓冲);
  70.         var 字节数码串=[],字符串=[],行号,四分隔,八分隔;
  71.         for(let 偏移=0;偏移<数组缓冲.byteLength;偏移++){
  72.                 var 字节数码=数据操作.getInt8(偏移);
  73.                 行号=Math.floor(偏移/16);
  74.                 if((偏移+1)%4){四分隔=''}else{四分隔=' '};
  75.                 if((偏移+1)%8){八分隔=''}else{八分隔=' '};
  76.                 if(typeof 字节数码串[行号]=="undefined"){字节数码串[行号]=''}
  77.                 var 字节高位=(字节数码>>>4&0xF).toString(16).toUpperCase(),字节低位=(字节数码&0xF).toString(16).toUpperCase();
  78.                 字节数码串[行号]+=字节高位+字节低位+" "+四分隔+八分隔;
  79.                 if(typeof 字符串[行号]=="undefined"){字符串[行号]=''}
  80.                 if(字节数码){字符串[行号]+=String.fromCharCode(字节数码);}else{字符串[行号]+=' ';}
  81.         }
  82.         for(let 行号=0;行号<字节数码串.length;行号++){
  83.                 var 十六进制行号=('000'+(行号<<4).toString(16)).slice(-4).toUpperCase();
  84.                 console.log(十六进制行号+":"+字节数码串[行号]+"\t["+字符串[行号]+"]");        //显示输出
  85.         }
  86. }
复制代码


验证参数可扩展!

评分

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

查看全部评分

 楼主| 发表于 2026-4-26 21:42:23 | 显示全部楼层
文本框输入内容,点击按钮:
  1. function 打开运行命令提示符测试(){
  2.         const 执行宏调用=ExecuteExcel4Macro;console.clear();
  3.         let 运行标题="运行",命令标题="打开命令提示符 - 运行";
  4.         var 运行句柄=执行宏调用(`CALL("User32","FindWindowA","JJF",0,"${运行标题}")`);
  5.         var 命令句柄=执行宏调用(`CALL("User32","FindWindowA","JJF",0,"${命令标题}")`);
  6.        
  7.         if(!(运行句柄|命令句柄)){
  8.                 console.log("打开运行对话框");let 参数运行="shell:::{2559a1f3-21d7-11d4-bdaf-00c04f60b9f0}";
  9.                 let 结果=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFFJJ",0,"open","explorer","${参数运行}",0,1)`);
  10.         }else{
  11.                 if(运行句柄){
  12.                         var 标题=命令标题,命令="CMD",句柄=运行句柄;
  13.                 }else{if(命令句柄){var 标题=运行标题,命令="control",句柄=命令句柄;}}
  14.                
  15.                 let 可显示=执行宏调用(`CALL("User32","IsWindowVisible","JJ",${句柄})`);
  16.                 执行宏调用(`CALL("User32", "SetWindowTextA", "JJF", ${句柄},"${标题}")`);
  17.                 console.log("句柄:"+句柄+"\t窗口名:"+获取窗口标题(句柄)+"\t类名:"+获取类名(句柄));
  18.                 if(获取类名(句柄)=="#32770" && 可显示){
  19.                         var 复合框句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFJ",${句柄},0,"ComboBox",0)`);        //复合框
  20.                         console.log("复合框句柄:"+复合框句柄+"\t窗口名:"+获取窗口标题(复合框句柄)+"\t类名:"+获取类名(复合框句柄));
  21.                         var 编辑框句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFJ",${复合框句柄},0,"Edit",0)`);        //编辑框
  22.                         console.log("编辑框句柄:"+编辑框句柄+"\t窗口名:"+获取窗口标题(编辑框句柄)+"\t类名:"+获取类名(编辑框句柄));
  23.                         let 设置文本=0xC;
  24.                         var 设置文本框内容=执行宏调用(`CALL("User32", "SendMessageA", "JJJJF", ${编辑框句柄},${设置文本},0,"${命令}")`);
  25.                        
  26.                         alert("按 空格 关闭此对话框以 运行 命令提示符");
  27.                         var 确定按钮句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFF",${句柄},0,"Button","确定")`);        //确定按钮
  28.                         console.log("确定按钮句柄:"+确定按钮句柄+"\t窗口名:"+获取窗口标题(确定按钮句柄)+"\t类名:"+获取类名(确定按钮句柄));
  29.                         let 点击=0xF5;        //消息点击BM_CLICK=0xF5‌
  30.                         let 点击确定=执行宏调用(`CALL("User32", "SendMessageA", "JJJJJ", ${确定按钮句柄},${点击},0,0)`);
  31.                 }
  32.         }
  33. }
  34. function 获取窗口标题(窗口句柄){
  35.         const 执行宏调用=ExecuteExcel4Macro;
  36.         let 窗口标题长度=执行宏调用(`CALL("User32", "GetWindowTextLengthA", "JJ", ${窗口句柄})`);
  37.         let 缓冲区大小=窗口标题长度+1,窗口标题="";
  38.         const 内存地址 = 执行宏调用(`CALL("Kernel32", "VirtualAlloc", "JJJJJ", 0, ${缓冲区大小}, ${0x3000}, 4)`);        //申请内存
  39.         let 标题长度=执行宏调用(`CALL("User32", "GetWindowTextA", "JJJJ", ${窗口句柄},${内存地址},${窗口标题长度+1})`);
  40.         if(标题长度){窗口标题=内存读取字符串(内存地址);}
  41.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  42.         return 窗口标题;
  43. }
  44. function 获取类名(窗口句柄){
  45.         const 执行宏调用=ExecuteExcel4Macro;
  46.         let 缓冲区大小=256,类名="";        //类名最长255
  47.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${缓冲区大小},${0x3000},4)`);        //申请内存
  48.         let 类名长度=执行宏调用(`CALL("User32","GetClassNameA","JJJJ",${窗口句柄},${内存地址},${缓冲区大小})`);
  49.         if(类名长度){类名=内存读取字符串(内存地址);}
  50.         执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);        //释放内存
  51.         return 类名;
  52. }
  53. function 内存读取字符串(内存地址){        //返回字符串
  54.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  55.         const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  56.         let 偏移字节=0,文本字符串=分段文本='';
  57.         while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  58.                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  59.                 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  60.                 文本字符串+=分段文本;
  61.         }
  62.         return 文本字符串;
  63. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-13 21:45

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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