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

办公软件WPS的JSA中列出窗口菜单

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


列举记事本所有菜单文本:(请先打开一个记事本!
  1. function 显示窗口所有菜单测试(){        //记事本窗口
  2.         console.clear();
  3.         let 记事本句柄=查找窗口(0,"Notepad");        //按记事本类查找
  4.         if(!记事本句柄){alert("未找到记事本!退出");return;}
  5.         显示菜单(记事本句柄);
  6. }
复制代码


打开记事本的字体对话框,相单于点击了菜单“格式》字体”:
  1. function 查找窗口菜单并操作测试(){        //找一个记事本窗口,(模拟菜单)打开字体对话框
  2.         console.clear();
  3.         let 记事本句柄=查找窗口(0,"Notepad");        //按记事本类查找
  4.         if(!记事本句柄){alert("未找到记事本!退出");return;}
  5.        
  6.         let 菜单组=查找菜单(记事本句柄,"字体");
  7.         console.log("菜单组:"+菜单组);
  8.         if(菜单组.length==1){
  9.                 console.log("只找到一个:"+菜单组[0]);
  10.                 let 执行命令=0x111;
  11.                 投送带参消息(记事本句柄,执行命令,菜单组[0][1],0);        //相当于点击字体菜单项,打开字体对话框
  12.         }
  13. }
复制代码


用到的函数:
  1. function 发送带参消息(窗口句柄,消息,短参,长参){        //短参16位,长参32位
  2.         const 执行宏调用=ExecuteExcel4Macro;
  3.         执行宏调用(`CALL("User32","SendMessageA","JJJJJ",${窗口句柄},${消息},${短参},${长参})`);
  4. }

  5. function 投送带参消息(窗口句柄,消息,短参,长参){        //短参16位,长参32位
  6.         const 执行宏调用=ExecuteExcel4Macro;
  7.         执行宏调用(`CALL("User32","PostMessageA","JJJJJ",${窗口句柄},${消息},${短参},${长参})`);
  8. }

  9. function 查找窗口(标题,类){        //返回句柄
  10.         const 执行宏调用=ExecuteExcel4Macro;
  11.         var 窗口句柄;
  12.         if(!标题){        //标题为0               
  13.                 if(!类){        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JJJ",0,0)`);        //类为0
  14.                 }else{        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${类}",0)`);}
  15.         }else{
  16.                 if(!类){        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JJF",0,"${标题}")`);        //类为0
  17.                 }else{        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JFF","${类}","${标题}")`);}
  18.         }
  19.         return 窗口句柄;
  20. }

  21. function 显示菜单(窗口句柄){        //显示窗口主菜单文本
  22.         let 菜单句柄=获取菜单(窗口句柄);
  23.         let 菜单数=获取菜单数(菜单句柄);
  24.         let 菜单标识=0x400;
  25.         for(let i=0;i<菜单数;i++){        //菜单序号i
  26.                 let 菜单文本=获取菜单文本(菜单句柄,i,菜单标识);
  27.                 let 菜单号=获取菜单号(菜单句柄,i);
  28.                 if(菜单号==-1){
  29.                         console.log("菜单文本(+):"+菜单文本);
  30.                         显示子菜单(菜单句柄,i);
  31.                 }else{console.log("菜单文本(-):"+菜单文本+"\t菜单号:"+菜单号);}
  32.         }
  33. }

  34. function 显示子菜单(菜单句柄,菜单序号){        //显示子菜单文本(菜单号为0的一般为分隔线)
  35.         let 子菜单句柄=获取子菜单(菜单句柄,菜单序号);
  36.         let 子菜单数=获取菜单数(子菜单句柄);
  37.         let 子菜单标识=0x400;
  38.         for(let i=0;i<子菜单数;i++){        //子菜单序号i
  39.                 let 子菜单文本=获取菜单文本(子菜单句柄,i,子菜单标识);
  40.                 let 子菜单号=获取菜单号(子菜单句柄,i);
  41.                 if(子菜单号==-1){
  42.                         console.log("子菜单文本(+):"+子菜单文本);
  43.                         显示子菜单(子菜单句柄,i);        //分隔线的菜单号为0
  44.                 }else{console.log("子菜单文本(-):"+子菜单文本+"\t子菜单号:"+子菜单号);}
  45.         }
  46. }

  47. function 查找菜单(窗口句柄,部分菜单文本){
  48.         let 菜单句柄=获取菜单(窗口句柄);
  49.         let 菜单数=获取菜单数(菜单句柄);
  50.         let 菜单标识=0x400;var 菜单组=[];
  51.         for(let i=0;i<菜单数;i++){        //菜单序号i
  52.                 let 菜单文本=获取菜单文本(菜单句柄,i,菜单标识);
  53.                 let 菜单号=获取菜单号(菜单句柄,i);
  54.                 if(菜单号==-1){
  55.                         查找子菜单(菜单句柄,i,部分菜单文本,菜单组);
  56.                 }else{
  57.                         if(菜单文本.indexOf(部分菜单文本)!=-1){
  58.                                 菜单组.push([菜单文本,菜单号]);
  59.                         }
  60.                 }
  61.         }
  62.         return 菜单组;
  63. }

  64. function 查找子菜单(菜单句柄,菜单序号,查找内容,菜单组){
  65.         let 子菜单句柄=获取子菜单(菜单句柄,菜单序号);
  66.         let 子菜单数=获取菜单数(子菜单句柄);
  67.         let 子菜单标识=0x400;
  68.         for(let i=0;i<子菜单数;i++){        //子菜单序号i
  69.                 let 子菜单文本=获取菜单文本(子菜单句柄,i,子菜单标识);
  70.                 let 子菜单号=获取菜单号(子菜单句柄,i);
  71.                 if(子菜单号==-1){
  72.                         查找子菜单(子菜单句柄,i,查找内容,菜单组);        //分隔线的菜单号为0
  73.                 }else{
  74.                         if(子菜单文本.indexOf(查找内容)!=-1){
  75.                                 菜单组.push([子菜单文本,子菜单号]);
  76.                         }
  77.                 }
  78.         }
  79. }

  80. function 获取菜单(窗口句柄){        //标准窗口的菜单对象句柄
  81.         const 执行宏调用=ExecuteExcel4Macro;
  82.         let 菜单句柄=执行宏调用(`CALL("User32","GetMenu","JJ",${窗口句柄})`);
  83.         return 菜单句柄;
  84. }

  85. function 获取菜单数(菜单句柄){
  86.         const 执行宏调用=ExecuteExcel4Macro;
  87.         let 菜单数=执行宏调用(`CALL("User32","GetMenuItemCount","JJ",${菜单句柄})`);
  88.         return 菜单数;
  89. }

  90. function 获取菜单号(菜单句柄,菜单序号){
  91.         const 执行宏调用=ExecuteExcel4Macro;
  92.         let 菜单号=执行宏调用(`CALL("User32","GetMenuItemID","JJJ",${菜单句柄},${菜单序号})`);
  93.         return 菜单号;        //返回-1表示有子菜单
  94. }

  95. function 获取子菜单(菜单句柄,菜单序号){
  96.         const 执行宏调用=ExecuteExcel4Macro;
  97.         let 子菜单句柄=执行宏调用(`CALL("User32","GetSubMenu","JJJ",${菜单句柄},${菜单序号})`);
  98.         return 子菜单句柄;
  99. }

  100. function 获取菜单文本(菜单句柄,菜单序号,菜单标识){
  101.         const 执行宏调用=ExecuteExcel4Macro;
  102.         let 菜单文本长度=执行宏调用(`CALL("User32","GetMenuStringA","JJJFJJ",${菜单句柄},${菜单序号},"",0,${菜单标识})`);
  103.         let 内存地址=申请虚拟内存(菜单文本长度+1);
  104.         执行宏调用(`CALL("User32","GetMenuStringA","JJJJJJ",${菜单句柄},${菜单序号},${内存地址},${菜单文本长度+1},${菜单标识})`);
  105.         let 菜单文本=内存读取字符串(内存地址);
  106.         释放虚拟内存(内存地址);
  107.         return 菜单文本;
  108. }

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

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

  118. function 内存读取字符串(内存地址){        //返回字符串
  119.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  120.         const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  121.         let 偏移字节=0,文本字符串=分段文本='';
  122.         while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  123.                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  124.                 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  125.                 文本字符串+=分段文本;
  126.         }
  127.         return 文本字符串;
  128. }
复制代码


发表于 1 小时前 | 显示全部楼层
收下了,这个很强大感谢楼主分享
回复

使用道具 举报

发表于 18 分钟前 | 显示全部楼层
收下了,这个很强大感谢楼主分享
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-29 20:58

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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