aardio,你用过吗?
话不多说,选择重点说明。
1.引入java类
当需要使用java类时,只需将其放入java文件夹下即可,具体包名可以自定义。实际上为了方便,会先创建包,然后创建java类,在里面编写代码后,将其编译为class文件,即可引入使用。(还有一种方式就是只编写java代码,然后通过aardio自带的命令进行编译,但本人主要写java的,所以直接编译成class)
重点有以下几个:
①aardio在引入时只需要.class文件,其实并不需要.java文件,放java文件是为了方便编辑源码;
可以在java文件所在目录打开cmd通过javac命令进行编译
javac -encoding UTF-8 MD5Utils.java
②包名一定要对应(class文件和引入时的包名);
③若java文件中引入了外部的jar,则需要将其放入java文件所在目录,然后再编译,同时需要指定jar(当有多个jar时,之间使用;分隔)
javac -encoding UTF-8 -cp commons-codec-1.15.jar MD5Utils.java
编译为class文件后即可使用,然后调用其方法,其中上述截图的引入的java代码部分截图如下
当然也可以将其打成jar包,这里就简单说明一下:
在cmd执行,将其打成jar
jar -cvf MD5Utils.jar MD5Utils.class
然后使用解压软件,比如rar,打开文件META-INF/MANIFEST.MF,在最后指定主启动类
Main-Class: MD5Utils
然后就可以使用java -jar命令运行里面的方法了(不过里面需要包含main方法)
2.自定义用户库
当一些重复的代码,按照java的思想是一定要进行封装的,比如工具类。下面对MD5的工具类进行封装说明(需要引入java)
只需要在用户库新建库,然后在里面编写方法即可。需要注意的是,这里要使用外部的包,必须要使用..。
定义后在调用的代码中先导入,然后使用即可
3.判断程序是否重复运行
一般情况下,一个应用程序启动后,只会创建一个实例,不会重复的启动,那么就可以通过窗口局句柄来进行判断
第一步,先获取唯一的实例ID
先在右侧的工具里面生成了GUID,这个ID几乎是国际唯一的,可以用来唯一标识应用。
第二步,引入所需要的包,获取窗口并进行判断
当启动后,再次运行就会提示,只能退出后再运行。
4.常见的命令和方法
4.1命令
常规的一些命令如下表,方法的参数在此略,具体的在调用时会有提示
方法名 | 说明 | 引入 | 示例 |
process.execute() | 执行某个进程 | import process |
process.execute("/QQ.exe");启动QQ的应用程序 |
process.kill() | 强制杀死某个进程 | import process |
process.kill("/QQ.exe");强制关闭QQ程序 |
loadcodex() | 动态加载并运行aardio代码 | - |
见后续示例 |
loadcode() | 加载aardio代码 | - |
见后续示例 |
win.getText() | 获取窗口句柄的文字(窗口标题) | - |
winform.msgbox(win.getText(winform.hwnd)) |
table.push() | 向数组尾部添加一个或多个元素,返回数组大小 | - |
var arr={};table.push(arr,1); |
table.insert() | 向数组头部添加一个或多个元素,返回数组大小 | var arr={};table.push(arr,1); | |
table.clear() | 清除数组中的所有元素 | - | var arr={1,2,3};table.clear(arr); |
1)loadcodex()示例
使用loadcodex可减少主文件中的代码量,对不同的逻辑进行分离,通过动态加载,可以减少界面的卡顿。
先定义一个代码文件tools.aardio,用于进行业务的处理,这里以获取笑话为例(通常工具类是放在用户库(lib文件夹下),业务的处理单独处理)
import web.rest.jsonClient; var http = web.rest.jsonClient(); var url="https://autumnfish.cn/api"; //获取笑话 getJokes = function(){ return http.get(url+"/joke/list?num=10") }
使用loadcodex加载tools.aardio,并调用其中的方法
winform.button.oncommand = function(id,event){ //加载文件 loadcodex("\function\tools.aardio"); //可直接调用方法,因为此时文件已加载 var context = getJokes() winform.msgbox(context) }
需要注意的是,这里引入后可直接使用方法。那么在多个文件定义方法时尽量避免重名,否则在调用时,则会以最后的那个方法为准。
2)loadcode()示例
loadcode()和loadcode()x是很类似的。其原型是
函数对象,错误信息 = loadcode( codeString | filepath )
loadcode()仅仅加载代码,该函数并不立即执行代码,而是返回一个函数对象,然后在需要使用的时候才会运行其代码。如果加载代码失败,则返回的函数对象为null值,并在第二个返回值中返回错误信息.
loadcodex()加载代码并且运行代码,重在立即执行里面的代码。
如果只是想运行一下代码用loadcodex()就可以,如果是想加载了代码以后反复运行,就先用 loadcode() 加载为一个函数对象,然后再去调用。
先定义一个文件tools2.aardio
在主文件main.aardio加载
在我看来,其实loadcodex()完全可以替代loadcode()。至于两者在性能上有何不同,暂不可知。
4.2 按行读取txt文件
readline = function(path){ var txt = string.load(path); if(txt==null){ return null; } return string.split(txt,'<\r\n>'); }
可以使用string类来读取文件,然后通过换行符进行分隔,返回按行组成的数组。
5.全局变量的定义与使用
有时可以需要在main.aardio中定义全局变量,然后在其他的文件中使用,因此全局变量也是很重要的,也非常的简单,只需要使用..修饰,就是全局变量
如在main.aardio定义数据类型
然后在文件中使用即可
6.提示框
6.1 msgbox-默认对话框
其语法如下(标题可省略,默认为当前窗口的标题【属性-标准-标题】)
对于普通的消息提示,可以直接使用,不过需要点击确定。
对于错误的提示,也可以提示
6.2 msgOk、msgErr、msgInfo、msgAsk-提示框
msgOk其语法如下,其他类似,使用时需要导入包win.dlg.message
对于成功的操作可进行正确的提示,然后使其自动关闭。
同理,操作失败也可以进行提示
那么,对于普通的消息提示,不区分正确和错误,也是可以进行提示
除此之外,其也提供了询问的对话框,样式还是比较好看的。
语法如下:
示例截图如下:
对于普通的消息提示,除了图标是感叹号外,还可以显示皱眉、大拇指、倒竖大拇指,警告
6.3 msgboxTest-询问对话框
其语法如下(标题可省略)
对于需要询问的对话框,采用这种方式最佳。
这里点击确定或取消,进行了消息的提示,实际场景可根据需要进行逻辑的处理。
6.4文本框提示
对于文本框的内容,如果输入的不正确,可对其进行提示
窗体文件如下
//文本框提示 import win.ui; /*DSG{{*/ var winform = win.form(text="aardio form";right=455;bottom=231) winform.add( btnError={cls="button";text="错误";left=48;top=152;right=152;bottom=184;z=2}; btnInfo={cls="button";text="提示";left=304;top=152;right=400;bottom=184;z=4}; btnWarning={cls="button";text="警告";left=176;top=152;right=272;bottom=184;z=3}; edit={cls="edit";text="Edit";left=80;top=40;right=345;bottom=79;edge=1;multiline=1;z=1} ) /*}}*/ winform.btnError.oncommand = function(id,event){ winform.edit.showErrorTip("这是标题","这是要显示的错误信息") } winform.btnWarning.oncommand = function(id,event){ winform.edit.showWarningTip("这是标题","这是要显示的错误信息") } winform.btnInfo.oncommand = function(id,event){ winform.edit.showInfoTip("这是标题","这是要显示的错误信息",true) } winform.show(); win.loopMessage();
运行后点击错误按钮,文本框会显示错误的信息,其他的类型同理
6.5自定义气泡提示
有时组件不能满足需要,可进行自定义,这种组件需要指定坐标,这里以从屏幕右下角显示为例。
import winex.tooltip; /* 不指定最后一个超时参数,则鼠标点击任意位置关闭。 参数 @2,@3 指定显示提示的 x,y 坐标,不指定坐标则取鼠标当前坐标。 参数 @1 指定要显示的内容,如果包含换行,则第一行显示为标题(同时显示关闭按钮)。 */ winex.tooltip.balloon('系统提示\n这是提示内容,你看得见我吗?我会自动关闭',1800,1000,10000/*超时毫秒数*/); win.loopMessage();
就是根据坐标设置提示框的位置。
6.6通知窗口
当有新消息时,也可以模仿操作系统的通知,弹出消息通知框。
先封装为一个组件messageInfo.aardio
//通知窗口 import win.ui; /*DSG{{*/ var winform = win.form(text="aardio form";right=271;bottom=127;bgcolor=15780518;border="none";exmode="toolwindow";parent=...;topmost=1) winform.add( static={cls="static";left=24;top=40;right=248;bottom=104;transparent=1;z=1} ) /*}}*/ import win.util.popup var info = ...; //使窗口在屏幕右下角弹出 pop = win.util.popup(winform) pop.countdown=function(remaintime){ winform.static.text = info; if(remaintime==0){ winform.close(); } } winform.show(true) win.loopMessage(); return winform;
然后调用
var messageInfo = loadcode("\function\popupinfo.aardio") messageInfo("恭喜你,获取了一个红包")
运行后,就会在屏幕右下角弹出提示,10秒后自动关闭,不过默认的样式有点丑,具体可根据需要进行美化。
7.键盘的监听
如果想对键盘输入的内容进行处理后再返回,那就需要监听键盘(条形码的扫码枪也是一种输入设备,扫描条码后输出一串数字并回车)。
下面的案例是对键盘进行监听数字的输入:
- 当输入类型是扫码枪时,输入的是数字并且回车后,才会显示数字(这里可以对输入的数字进行处理,比如扫码追溯码,将其转换为商品码),非数字不做处理,直接输出
- 当输入类似是手工输入时,无论是数字或其他字符,都直接输出
import win.ui; import winex; import key; import key.hook; /*DSG{{*/ var winform = win.form(text="我的工具";right=555;bottom=175) winform.add( edit={cls="edit";left=48;top=16;right=496;bottom=96;edge=1;multiline=1;z=1}; static={cls="static";text="输入方式(F1):";left=48;top=128;right=128;bottom=152;transparent=1;z=2}; static2={cls="static";text="扫码枪";left=136;top=128;right=280;bottom=152;transparent=1;z=3} ) /*}}*/ var arr={}//记录输入的数字 var hook = key.hook(); var keydown = {}//记录键按下 var isScanner = true; //判断是否按了shift isShift =function(vkcode){ return vkcode==16 || vkcode==160 || vkcode==161 } //判断是否按下了某个键 isDownKey = function(vkcode,k){ var rs = false; for(i=1;#keydown;1){ var e = keydown[i]; if(k=='shift'){ if(isShift(e)){ rs = true; break; } } } return rs; } //键盘钩子:返回true表示禁用,返回false表示放行 hook.proc=function(msg,vkcode,scancode){ var kname = key.getName(vkcode); select(msg) { case 0x100/*_WM_KEYDOWN*/ ,0x104/*_WM_SYSKEYDOWN*/ { if(vkcode == 112/*F1,扫码枪和手工输入切换*/){ isScanner = !isScanner; if(isScanner){ winform.static2.text="扫码枪"; }else{ winform.static2.text="手工输入"; } } var shiftDown = isShift(vkcode) if(shiftDown){ //记录按下shift table.push(keydown,vkcode); } //记录输入的数字,有复合键时不处理 if(#keydown==0){ if ((vkcode >= 48 && vkcode <= 57 ) || (vkcode >= 96 && vkcode <= 105) ){ //对数字键盘进行处理,否则kname是NUMPAD1信息 if(vkcode >= 96 && vkcode <= 105)kname=vkcode-96 table.push(arr,kname); //return ''可视为拦截了消息,然后通过winex.say发送新消息,否则不处理; if(isScanner)return ''; } if(vkcode==13/*回车*/){ //清空按键按下的数组 table.clear(keydown) if(isScanner){ //将数组转换为字符串 var strx = string.join(arr); //获取当前窗口句柄 var hwndx = win.getForeground(); //发送消息,这里可以对消息进行处理后再发送 winex.say(strx,hwndx); } table.clear(arr) } } } case 0x101/*_WM_KEYUP*/,0x105/*_WM_SYSKEYUP*/ { //如果按下了shift var shiftDown = isDownKey(vkcode,'shift') //是否弹起了shift var shiftUp = isShift(vkcode) /**对数字的输入有几种情况: 1.没有按下shift 2.按下了shift并未弹起(组合键) 3.按下了shift并且弹起了 对于1和3可直接处理 清除按键按下的数组的shift记录,2不予处理。 **/ if(shiftDown && shiftUp) table.clear(keydown) } } return false; } winform.show() win.loopMessage();
上述的代码,看起来还是很简单的。截图如下:
一开始,我本想通过键盘钩子返回true和false来拦截并处理消息,但当返回true时,会禁止输入,会影响其他程序的正常使用,故更换了一种方式,就是在select中通过是否返回空字符来阻止消息的输出,可视为要阻止消息,那么在获取到消息后将其替换为空字符进行输出,在这个过程中对拦截的消息进行处理后再发送消息给操作系统。
8.菜单
一个普通的应用也是有菜单栏的,那么添加菜单也很简单,示例运行效果如下图
对应代码如下
//窗口菜单 import win.ui; import win.ui.menu; import win.dlg.message; /*DSG{{*/ var winform = win.form(text="菜单用法演示";right=497;bottom=345;border="dialog frame";max=false;min=false;topmost=1) winform.add() /*}}*/ var t = 3*1000;//弹框关闭时间,3s//创建弹出菜单,可以在这里创建,也可以使用后面的主菜单的addTable()进行创建 var menuFile = win.ui.popmenu(winform); /** add方法 参数1 菜单名称 参数2 function 可在里面执行代码 **/ menuFile.add("打开",function(id){ winform.msgInfo("打开文件",t) }) menuFile.add("保存",function(id){ winform.msgInfo("保存文件咯",t) }) var menuSystem = win.ui.popmenu(winform); menuSystem.add("背景",function(id){ winform.msgInfo("设置系统背景",t) }) //除了使用add,也可以使用弹出菜单的addTable()进行创建 menuSystem.add(); //添加分隔线 menuSystem.addTable( { { "字体";function(id){ createMenuFunction("\dlg\font.aardio"); }}; { /*---分隔线---*/ }; { "退出"; function(id){ winform.close() }}; } ) //加载窗体文件 createMenuFunction = function(formPath){ winform.show(false)
win.loadForm(formPath) } //创建主菜单,主菜单构建完成后要用menu.redraw()更新,menu.addTable()会自动调用redraw() var menu = win.ui.menu(winform); menu.add('文件',menuFile) menu.add('设置',menuSystem) menu.addTable({ { "帮助";{ {"关于";function(id){ createMenuFunction("\dlg\help.aardio"); }}; {"检查更新";function(id){ winform.msgbox("当前已是最新版本") }} }}; { "布局"; { { "横向排列"; function(id){ winform.msgInfo("横向排列",t) } }; {/*---分隔线---*/ }; { "竖向排列"; function(id){ winform.msgInfo("竖向排列",t) } } } }; } ) //设置只有一个选择的菜单 menu.add('隐藏(F10)',function(id){ winform.show(false); }); menu.add('关闭(F9)',function(id){ winform.close() }); winform.show() win.loopMessage();
关于代码引用的两个文件,自定义后指定正确的路径即可。
需要注意的是,在主界面打开子菜单时,会隐藏主界面,关闭子菜单时,会显示主界面,如果需要关闭时就能看到主界面,也就是主界面保持为当前最前的窗口,那么需要设置主界面窗口顶置,topmost=1,这个是属性里面也可以设置
9.程序托盘图标
一个应用程序,都有自己的图标,也会在任务栏创建托盘,以便在窗口隐藏或最小化时还能找到。下面创建了一个普通的托盘图标,先看效果图
上代码
import win.ui; /*DSG{{*/ var winform = win.form(text="托盘图标";right=415;bottom=175;max=false) winform.add( static={cls="static";text="托盘图标的基本用法";left=136;top=64;right=408;bottom=88;notify=1;transparent=1;z=1} ) /*}}*/ var isFront = true;//是否显示在最前面 //下面创建托盘图标 当设置程序的图标后(工程-属性-程序图标),就无须再指定托盘的图标,默认会使用程序的图标 import win.util.tray; winform.tray = win.util.tray(winform) //设置鼠标提示 winform.tray.tip = "百宝箱" //设置托盘消息通知 winform.tray.pop('恭喜你使用百宝箱,快来试试看吧',"消息通知"); //点击最小化按钮时触发 winform.onMinimize = function(lParam){ winform.tray = win.util.tray(winform); winform.show(false); //隐藏窗口 return true;//阻击默认消息传递,取消最小化过程 } //托盘的消息处理 winform.onTrayMessage = { [0x205/*_WM_RBUTTONUP 单击右键*/ ] = function(wParam){ //弹出托盘菜单以前,一定要前置主窗口中,避免不点击菜单不会消失,父窗口隐藏也要这样做 win.setForeground(winform.hwnd) import win.ui.menu; winform.popmenu = win.ui.popmenu(winform);//创建弹出菜单 winform.popmenu.add('退出',function(id){ winform.close() }) winform.popmenu.popup(); winform.popmenu.close(); }; [0x202/*_WM_LBUTTONUP 单击左键*/] = function(wParam){ if(isFront){ winform.show(false); isFront = false; }else{ winform.show(true); isFront = true; } }; [0x203/*_WM_LBUTTONDBLCLK 双击左键*/] = function(wParam){}; [0x404/*_PARAM_DESTROY*/] = function(wParam){}; [0x405/*_PARAM_CLICKED*/] = function(wParam){}; } winform.show() win.loopMessage();
对于图标,只需设计工程的图标即可,格式是一个icon的图片,设置截图如下:
需要说明的是,在上述的效果图中,通知时,最下面有一行的小字,这个小字就是程序的说明,由于此时并没有打包运行,故显示的是开发工具的名称,而打包后就会显示工程属性中的 "文件描述" 信息。
10.开机启动
很多时候,想要软件开机启动,则只需要将其加到操作系统的注册表中即可。
import fsys; import win.reg; var exePath = fsys.getCurDir()+'\bbxClient.exe'; var reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"); reg.setValue('DrugstoreClient',exePath)//加入到注册表,相当于开机启动 reg.delValue("DrugstoreClient");//删除,相当于不开机自启
把exe添加到用户启动注册表后,下次开机就会自启。