(自用)AAR里一些好玩的功能

最近aar作者Jacen He更新了一些新库:

二维码和条形码的识别库Zbar

//生成测试二维码
import qrencode.bitmap;
var qrBmp = qrencode.bitmap("http://www.stm32cube.com/#Stm32cube中文网" );
qrBmp.copyBitmap(100).save("/qrcode.jpg",80) 
 
//识别二维码    
import zbar;
import soImage; //此扩展库要使用最新版

var img = soImage();
img.load("/qrcode.jpg");//加载二维码图像
img.grayScale();
    
scanner = zbar.scanner();
scanner.config('qrcode.enable');//可省略

import console;
scanner.scan(img.getData(),img.getWidth(),img.getHeight(),function(typeName,data){
     console.log(typeName,data)
    })
     
    
console.pause();

blob.png

二维码和条形码的应用挺广泛的,这个库实用性很大,先前也实现过类似功能,不过用的调用js的方法.

65 个评论

作者更进一步写了一个调用扫描仪然后识别扫描图像中的二维码的示例:

在这个代码里可以熟悉com组件的调用,和zbar的使用:

import console;
import com;

//连接扫描仪
//参考 https://msdn.microsoft.com/en-us/library/windows/desktop/ms630827(v=vs.85).aspx
var cdc = com.CreateObject("WIA.CommonDialog");
var device = cdc.ShowSelectDevice(cdc.ScannerDeviceType,true,false);
var scannerDevice = device.Items(1);

//设置扫描仪属性
scannerDevice.setProperties("Horizontal Resolution",300);
scannerDevice.setProperties("Vertical Resolution",300);
scannerDevice.setProperties("Current Intent",scannerDevice.ColorIntent);

//获取图像
var imageFile = scannerDevice.Transfer(cdc.wiaFormatJPEG);

/*
var imageFile = cdc.ShowAcquireImage(cdc.ScannerDeviceType
    ,cdc.ColorIntent,cdc.MaximizeQuality, "{00000000-0000-0000-0000-000000000000}"
    ,true,true,false);
*/

//识别扫描图像中的二维码
import soImage;
import zbar;
if(imageFile){
    var img = soImage();
    img.setBytes(imageFile.FileData.BinaryData,"*.bmp");
    img.grayScale();
    img.save("/test.jpg");

    scanner = zbar.scanner();
    scanner.config('disable');
    scanner.config('qrcode.enable');
    
    scanner.scan(img.getData(),img.getWidth(),img.getHeight(),function(typeName,data){
            console.log(typeName,data);
        })
}                                   

console.pause();

blob.png

当然没有扫描仪的童鞋是测试不了了..

听群里大神说可以弄成摄像头,然后截取一帧的图像,然后识别图像中的二维码.....

获取图片的高度和宽度:

blob.png

import soImage;

var img = soImage();

img.load("/1111.png");//加载二维码图像
//img.grayScale();//转化为灰度图片
import console;

console.log(img.getWidth(),img.getHeight())//获取图片宽度和高度
    
console.pause();


(转)搜图扩展库(soImage)最简单的屏幕找图示例:

import win.ui;
/*DSG{{*/
var winform = win.form(text="请稍候正在打开网页......";right=759;bottom=469)
/*}}*/

//导入浏览器控件支持库
import web.form; 

//在winform上建立浏览器控件窗口
var wb = web.form( winform  ); 

//打开网页
wb.go("http://bbs.aardio.com/forum-image-1.html");

//显示窗口
winform.show();   

//等待指定HTML节点(匹配tagName,src等节点属性)
wb.waitQueryEles( tagName="img"; src="aardio\.png" )
win.delay(1000);//给点时间让图像显示出来

import soImage;//导入搜图扩展库
import inet.http;//导入HTTP支持库

winform.text = "请稍候,下在下载样本数据"
var imgBytes = inet.http().get("http://bbs.aardio.com/static/image/common/aardio.png");

//创建查找图像
var imgFind = soImage();
imgFind.setBytes( imgBytes,"*.png"); //解析下载的图像数据,注意要指定图像文件后缀名
imgFind.crop(29,33,193,55);//裁剪图像,尽可能去掉背景,保留特征最强的部分

//创建屏幕图像
var imgScreen = soImage();
imgScreen.capture(winform.hwnd); //窗口截图

//在屏幕上查找图像
var sm,x,y = imgFind.findImage(imgScreen  );
winform.text = "已找到图片,相似度:" + sm;

//移动鼠标
import mouse;
x,y = win.toScreen(winform.hwnd,x,y); //窗口坐标转换为屏幕坐标
mouse.moveTo(x-50,y-50,true);//保留鼠标轨迹模仿真实的鼠标移动
mouse.click();//点击鼠标

//启动消息循环
win.loopMessage();

GIF.gif这个示例效果是: 自动下载了个特征图片,然后再winform窗口打开了一个网页,在网页里查找是否有这张类似的图片,找到后模拟鼠标移动到此图片位置,然后点击...

转自:http://bbs.aardio.com/forum.php?mod=viewthread&tid=9129&from=portal

转自一鹤微信公众号: aardio调用打印机示例:

https://mp.weixin.qq.com/s/HF6CwFNHXuyL_0GEUjf8jw

调用API打印其实非常简单,aardio调用API的语法也很简单,下面是一个最简单的例子:

Winspool = raw.loadDll("Winspool.drv");

var buffer = raw.buffer(1024)
var length = { INT value = 1024};
if(!Winspool.GetDefaultPrinter(buffer,length) )return;

var hdcPrint = ::Gdi32.CreateDC(null, buffer, null, null);

class DOCINFO {
    int cbSize = 20;
    ustring docName;
    ustring output;
    ustring datatype;
    INT fwType;
}
::Gdi32.StartDoc(hdcPrint,DOCINFO());
::Gdi32.StartPage(hdcPrint);

::Gdi32.TextOut(hdcPrint,20,20,"测试打印",4);

::Gdi32.EndPage(hdcPrint);
::Gdi32.EndDoc(hdcPrint); 
::Gdi32.DeleteDC(hdcPrint);

得到打印机的绘图设备句柄hdcPrint以后,就可以使用GDI或GDI+任意输出图文了。一个更简单的方法是使用浏览器控件(或者MSHTML组件)打印HTML格式的文档,代码也非常简单,示例如下:

import web.mshtml;
wbPrint = web.mshtml();
wbPrint.write("测试一下");
wbPrint.getDoc().execCommand("print");

如果需要显示打印对话框,则需要用到 ::Comdlg32.PrintDlg() 这个API,作者写了一个库 win.dlg.print用于调用这个API(其实这个库也只有几句代码),下面是一个完整的示例:

blob.png

//打印
import win.ui;
/*DSG{{*/
var winform = win.form(text="调用打印机";right=759;bottom=469)
winform.add(
btnEnumPrinters={cls="button";text="枚举打印机";left=441;top=193;right=692;bottom=261;z=4};
btnPrint={cls="button";text="调用API打印";left=441;top=32;right=692;bottom=100;z=1};
btnPrintDefault={cls="button";text="默认打印机输出";left=442;top=274;right=693;bottom=342;z=5};
btnWbPrint={cls="button";text="使用HTML打印";left=444;top=108;right=695;bottom=176;z=2};
edit={cls="edit";left=40;top=36;right=417;bottom=429;edge=1;multiline=1;z=3}
)
/*}}*/

winform.btnPrint.oncommand = function(id,event){
    import win.dlg.print;
    var printDlg = win.dlg.print(winform);
    if(!printDlg.doModal()) return;

    //开始打印
    class DOCINFO {
        int cbSize = 20;
        ustring docName;
        ustring output;
        ustring datatype;
        INT fwType;
    }
    ::Gdi32.StartDoc(printDlg.hdc,DOCINFO());
    ::Gdi32.StartPage(printDlg.hdc);

    //GDI+绘图
    import gdip.graphics;
    import gdip.family;
    var graphics = gdip.graphics(printDlg.hdc);
    var brush = gdip.solidBrush(0xFFFF0000);
    var family = gdip.family("宋体");
    var strformat = gdip.stringformat(); 
    var curFont = family.createFont(  15,2/*_GdipFontStyleItalic*/, 2/*_GdipUnitPixel*/)
    graphics.drawString( "Hellow world! 打印测试!!"  , curFont
    ,  gdip.RECTF(15,15,500,150), strformat,brush);
    brush.delete()
    curFont.delete()
    strformat.delete();
    family.delete(); 
     
    //结束打印    
    ::Gdi32.EndPage(printDlg.hdc);
    ::Gdi32.EndDoc(printDlg.hdc); 
    printDlg.free()   
}

winform.btnWbPrint.oncommand = function(id,event){
    import web.mshtml;
    wbPrint = web.mshtml();
    wbPrint.write("测试一下")
    wbPrint.getDoc().execCommand("print")
}

winform.btnEnumPrinters.oncommand = function(id,event){

    Winspool = raw.loadDll("Winspool.drv");
    
    var needed = {INT value}
    var returned = {INT value}
    Winspool.EnumPrinters(2/*_PRINTER_ENUM_LOCAL*/, null, 4, null, 0, needed, returned) ;
            
    var buffer = raw.buffer(needed.value)
    Winspool.EnumPrinters(2/*_PRINTER_ENUM_LOCAL*/, null, 4, buffer, #buffer, needed, returned) ;
    
    var info4 = raw.convert(buffer,{
        struct printers[] = {
            {
                ustring  printerName;
                ustring  serverName;
                INT   attributes;
            };
            length = returned.value;
        }
    })
    
    for(i=1;#info4.printers;1){ 
        winform.edit.print(info4.printers[ i ].printerName,info4.printers[ i ].attributes)
    } 
}

winform.btnPrintDefault.oncommand = function(id,event){

    Winspool = raw.loadDll("Winspool.drv");
    
    var buffer = raw.buffer(1024)
    var length = { INT value = 1024};
    if(!Winspool.GetDefaultPrinter(buffer,length) )return;
    
    var hdcPrint = ::Gdi32.CreateDC(null, buffer, null, null);
    
    class DOCINFO {
        int cbSize = 20;
        ustring docName;
        ustring output;
        ustring datatype;
        INT fwType;
    }
    ::Gdi32.StartDoc(hdcPrint,DOCINFO());
    ::Gdi32.StartPage(hdcPrint);

    ::Gdi32.TextOut(hdcPrint,20,20,"测试打印",4);
  
    ::Gdi32.EndPage(hdcPrint);
    ::Gdi32.EndDoc(hdcPrint); 
    ::Gdi32.DeleteDC(hdcPrint);
}

winform.show() 
win.loopMessage();


progress进度条的使用:

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=633;bottom=236)
winform.add(
button2={cls="button";text="开始";left=96;top=149;right=175;bottom=206;z=2};
progress={cls="progress";left=93;top=98;right=543;bottom=128;edge=1;max=100;min=0;z=1}
)
/*}}*/

winform.button2.oncommand = function(id,event){
    winform.progress.setRange(0,200)//设置最大和最小范围
    winform.progress.step = 10;//设置步进长度

for(i=1;20;1){
winform.progress.stepIt();//前进一步
win.delay(1)
}
}

winform.show() 
win.loopMessage();

注意:

设置范围要从零开始!!

再说利用html方式打印:

winform.btnWbPrint.oncommand = function(id,event){
    import web.mshtml;
    wbPrint = web.mshtml();
    //方式一: 直接取得网址内容并打印
    //wbPrint.go("http://www.aardio.com")
    //wbPrint.waitDoc()//等待页面加载完毕
    //方式一 结束
    //方式二 : 利用string.load加载本地文件
    wbPrint.write(string.load("C:\Users\Administrator\Desktop\新建文件夹\index.tpl.htm"));
    //方式二 结束

    wbPrint.getDoc().execCommand("print")
}


不常用的功能: 怎样编写注册控制后台服务程序范例:

主函数如下:

//RUNAS//
import service
 
//用于接收命令行参数并自动注册后台服务
if( #_ARGV ){
    for( i=1;#_ARGV ){ 
        if( _ARGV[i] == "/i" ){
            service.create( ,"testAardioSrv","Test Aardio Service","这是一个测试服务") 
     return;
        } 
        if( _ARGV[i] == "/u" ){
            service.delete( "testAardioSrv") 
     return;
        } 
    }
}

if( !_STUDIO_INVOKED ){

//这个函数用于在进程主线程中启动服务,并且会等待所有服务线程执行结束后才会返回
service.startDispatchThread(

     //可以增加多个服务名与服务线程回调函数的键值对
     testAardioSrv = function(serviceName,argv){ //注意此服务回调函数运行于独立线程
       
         import service.threads;
        
         //服务线程启动后第一件事应当是注册服务控制线程
         var srvStatus = service.registerCtrlThread(serviceName,service.threads.control)
        
         //服务切换到运行状态
         srvStatus.controlsAccepted = 0x1/*_SERVICE_ACCEPT_STOP*/ 
         srvStatus.currentState = 0x4/*_SERVICE_RUNNING*/;
         service.updateStatus(srvStatus,serviceName);
         
         //启动服务主线程
         service.threads.main(serviceName);
         
         //服务切换到停止状态
         srvStatus.controlsAccepted = 0;
         srvStatus.currentState = 0x1/*_SERVICE_STOPPED*/
         service.updateStatus(srvStatus,serviceName)
     }
)
}
else {
/*
后台服务程序本质也是一个控制台程序,
因为后台服务调试不便,开发环境下可以这样启动服务主线程,作为一个普通控制台程序进行调试。 

发布后需要在桌面显示控制台输出,请在控制面板->管理工具->服务管理器中右键点击注册的服务,属性中勾选:本地系统服务->允许与桌面交互。
更好的方法是使用日志文件代替控制台输出。
*/
import service.threads;
    service.threads.main("testAardioSrv");
}

用户库:


namespace service.threads;

//服务主线程
main = function(serviceName){
import service;
import thread.event; 
import console;

console.open()
var evt = thread.event("NT.SERVICE.CONTROL" + serviceName,false)
while( ! evt.wait(1000) ){  //每1000毫秒执行一次
console.log("服务正在运行",..time() )

}

//注意这也是一个独立的线程,用户控制服务停止或启动时都会触发此函数
control = function(control,eventType,pEventData){ 
    import service;
    import thread.event;
    
    var evtTask = thread.event("NT.SERVICE.CONTROL" + owner.serviceName,false); 
    
    if( control == 0x1/*_SERVICE_CONTROL_STOP*/ ){  
        //控制线程中更新srvStatus,第一个参数只要指定需要更新的字段就行了
        service.updateStatus({currentState = 0x3/*_SERVICE_STOP_PENDING*/},owner.serviceName);
        evtTask.set();//使事件对象切换为有信号状态,使wait函数退出  
    }
     
    return 0x0/*_NOERROR*/
}

运行效果:

blob.png

import com;
import console;


console.open();
adbs = com.CreateObject("Adodb.Stream"); 
adbs.setType(1)
adbs.setMode(3)
adbs.Open()

var array ={ _safearray = string.loadBuffer("C:\Users\Administrator\Desktop\新建文件夹(1)\1.jpg") }

adbs.Write(array)
adbs.SaveToFile("C:\Users\Administrator\Desktop\新建文件夹(1)\1_1.jpg",2)
adbs.Close()

execute("pause"

不知道干啥的。

刚刚aardio作者一鹤前辈发布了一个usbhid封装库,

同样是利用usbhidapi这个dll,代码风格征服了我,强!

网址:

 http://mp.weixin.qq.com/s/BQSByyfP6TM7zRwNid3AlQ


下面我把老大发的api库给大家看看:

namespace hid;

class device{
ctor( vendorId,productId,serialNumber){
if( type(vendorId) === type.string ){
this.hDevice = topointer( api.hid_open_path(path) );
..table.gc(this,"close");
}
elseif( type(vendorId) == type.pointer ){
this.hDevice = vendorId;
}
else {
if(serialNumber) serialNumber = ..string.toUnicode(serialNumber); 
this.hDevice = api.hid_open(vendorId,productId,serialNumber);
..table.gc(this,"close");
}
if(!this.hDevice) return null;
}; 
setNonblocking = function(enabled){
return api.hid_set_nonblocking(this.hDevice,!!enabled); 
}
errorMessage = function(){
var e = api.hid_error(this.hDevice);
if(e) return ..string.fromUnicode(topointer(e),,-1);
}
read = function(len=255){
var data = ..raw.buffer(len);
var len = api.hid_read(this.hDevice,data,len);
if(len<0) return null,this.errorMessage();
if(len){
return ..string.left(data,len);
}
}
readTimeout = function(milliseconds,len=255){
var data = ..raw.buffer(len);
var len = api.hid_read_timeout(this.hDevice,data,len,milliseconds);
if(len<0) return null,this.errorMessage();
if(len){
return ..string.left(data,len);
}
}
write = function(data,len,reportId){
if(!len) len = #data;
var p = ..raw.realloc(len+1);
p = ..raw.concat(p,reportId : '\0',1);
p = ..raw.concat(p,data,len);

var buf = ..raw.buffer(len+1);
var len = api.hid_write(this.hDevice,data,len+1);
p = ..raw.realloc(0,p);

if(len<0) return null,this.errorMessage();
return len;
}
getFeatureReport = function(reportId,len=255){
var data = ..raw.buffer(len+1);
data[1] = reportId;
var len = api.hid_get_feature_report(this.hDevice,data,len+1);
if( len < 0 )  return null,this.errorMessage();
if( len > 0) return string.sub(data,2,len);
}
sendFeatureReport = function(data,len,reportId){
if(!len) len = #data;
var p = ..raw.realloc(len+1);
p = ..raw.concat(p,reportId : '\0',1);
p = ..raw.concat(p,data,len);

var buf = ..raw.buffer(len+1);
var len = api.hid_send_feature_report(this.hDevice,data,len+1);
p = ..raw.realloc(0,p);

if(len<0) return null,this.errorMessage();
return len;
}
getManufacturerString= function(len=255){
  var data = ..raw.buffer(len*2);
  var err = api.hid_get_manufacturer_string(this.hDevice,data,len);
if( err )  return null,this.errorMessage(); 
return ..string.fromUnicode(data);
}
getProductString= function(len=255){
  var data = ..raw.buffer(len*2);
  var err = api.hid_get_product_string(this.hDevice,data,len);
if( err )  return null,this.errorMessage(); 
return ..string.fromUnicode(data);
}
getSerialNumberString= function(len=255){
  var data = ..raw.buffer(len*2);
  var err = api.hid_get_serial_number_string(this.hDevice,data,len);
if( err )  return null,this.errorMessage(); 
return ..string.fromUnicode(data);
}
getIndexedString= function(idx,len=255){
  var data = ..raw.buffer(len*2);
  var err = api.hid_get_indexed_string(this.hDevice,idx,data,len);
if( err )  return null,this.errorMessage(); 
return ..string.fromUnicode(data);
}
close = function(){
if(this.hDevice){
api.hid_close(this.hDevice);
this.hDevice = null;
};
}
@_meta;
}
 
namespace device{

//根据HIDAPI开源许可证可自由使用hidapi.dll组件:https://github.com/signal11/hidapi 
api = ..raw.loadDll($"~\lib\hid\.res\hidapi.dll","hidapi.dll","cdecl");
api.hid_init();

each = function(vendorId,productId){

var devs  = topointer( api.hid_enumerate(vendorId,productId) );
devs = ..gcdata(  
_topointer = devs; 
_gc = function(){
if(devs){
api.hid_free_enumeration(devs);
devs = null;
}

)
var next = devs;

return function(){
if(next){
var deviceInfo = ..raw.convert(next,{
string path;
WORD vendorId;
WORD productId;
ustring serialNumber;
WORD releaseNumber;
ustring manufacturerString; 
ustring productString; 
WORD usagePage;
WORD usage;
int interfaceNumber;
pointer next;
});
next = deviceInfo.next;
return deviceInfo;
}
else {
api.hid_free_enumeration(devs);
devs = null;
}

}


_meta = {
_serialize = function(kernelCall){
if(kernelCall) {
return "global.import('hid') : hid.device( topointer(" + tonumber(owner.hDevice) + ") ) "

}
};
}
}

/**intellisense()
hid = USB HID 通信接口
hid.device(.(vendorId,productId,serialNumber) = 打开设备返回句柄
hid.device(.(path) = 打开设备返回句柄,参数为each迭代器返回的deviceInfo.path
hid.device() = !stdhiddevice.
hid.each(vid,pid) = @for deviceInfo in hidapi.each() {

}
hid.device.each() = !hidapideviceInfo.
end intellisense**/


/**intellisense(!stdhiddevice)
setNonblocking(true) = 启用非阻塞模式
errorMessage() = 返回错误信息
read() = 读数据,可选使用参数@1指定缓冲区长度
readTimeout(__) = 读数据,参数@1指定毫秒单位的超时值,\n可选使用参数@1指定缓冲区长度
write(.(数据,长度,报告ID) = 写数据,除参数@1以外其他参数为可选参数
getFeatureReport() = 读功能报告,可选使用参数@1指定缓冲区长度
sendFeatureReport(.(数据,长度,报告ID) = 写功能报告,除参数@1以外其他参数为可选参数
getManufacturerString() = 读制造商字符串,可选使用参数@1指定缓冲区长度
getProductString() = 获取产品字符串,可选使用参数@1指定缓冲区长度
getSerialNumberString() = 获取序列号字符串,可选使用参数@1指定缓冲区长度
getIndexedString() = 获取索引字符串,可选使用参数@1指定缓冲区长度
close() = 关闭对象
end intellisense**/

/**intellisense(!hidapideviceInfo)
path = 设备路径
vendorId = 厂商ID
productId = 产品ID
serialNumber = 序列号
releaseNumber = 设备版本号
manufacturerString = 制造商,字符串
productString = 产品,字符串
usagePage = 使用页
usage = 使用ID
interfaceNumber = 接口编号
end intellisense**/

调用示例:

import console; 
import hid;

for(deviceInfo in hid.device.each() ){
console.dump(deviceInfo)
var device = hid.device(deviceInfo.vendorId,deviceInfo.productId)
if(device){ 
console.log(device.getProductString());
}
}

console.pause();


有没有办法实现一个库能够支持解压zip,7z,rar的?

io.print(fullpath);
var tpath = io.splitpath(fullpath);
select(string.lower(tpath.ext)
{
    case ".zip"{
        var ok,err = zlib.unzip.extract(fullpath,temp);
        io.print(ok,err);
    }
    case ".7z"{
        sevenZip.cmd.extract(fullpath,temp);
    }
    case ".rar"{
        var ok,err = fsys.unrar.extract(fullpath,temp);
        io.print(ok,err);
    }
}


监听窗体指令:

mainform.wndproc = function(hwnd,message,wPatam,lParam){
    select wParam{
        case 0xF060/*_SC_CLOSE*/ {
            process().terminate();//强制关闭窗体进程,防止进程残留
        }
        case 0xF020/*_SC_MINIMIZE*/ {
            console.debug("最小化");
        }
    }
}


(转)

再谈aardio控制打印机、条码打印机等

2017-08-29 Jacen He

aardio虽然实现很多功能代码较其他语言简洁,但aardio以及aardio生成的软件都非常小,并非象其他的编程语言那样依赖庞大的运行库 - 以体积换取易用性。一个常见的误解时:“增加体积就一定就会有更好的易用性”,这就好象坚持认为胖子一定比瘦子轻便,所以你经常听到很多人宣称:“语言并不重要,只要库够多就行了”,aardio并非如此,并不是你多写库模块多写代码或者写一个更庞大的开发工具就能比aardio方便。


就以调用打印机API而言(或者说调用C语言风格API),我上次给大家列举的代码例子,较之C#这样的巨无霸式的静态语言 - aardio仅仅需要更少的代码,更加的简洁,而且aardio他本身是一个动态语言,如果你用其他动态语言想方便的与C,C++提供的API直接交互 - 那可能非常的麻烦,所以动态语言通常被用来作为“脚本”使用(C,C++组件通常需要复杂的封装成为支持这个语言的接口),但aardio却被用来直接替代C++或C#完成大部分编程的全部代码 - 而很少被用来写脚本。即使你用aardio写网站时那好是像PHP那样在写服务端脚本(其实每种语言理论上都可以用来写脚本),但aardio的CGI.EXE仍然是用aardio编写(而非PHP那样使用C++编写EXE来运行PHP),所以使用aardio让人最愉快的就是,你只要掌握了aardio,你可以比较轻松的写出很多东西。

aardio不仅仅是调用API, 或者说调用C,C++组件非常简单(其实aardio调用Java,C#都同样的简单),我们还可以很方便的把常用的代码封装为“库”模块,所以aardio虽然小,提供的“库”却数量庞大(而很多库的代码都非常少),这次我再给大家演示一下,把上次发给大家的调用打印机的代码整理并放到了一个库里(见新版标准库的 sys.printer),你可以阅读库源码、或者查看新增的示例(aardio范例->操作系统->打印机),这个库的源码仍然非常的少(相对其他语言的各种模块组件的体积而言),而且并非像一些人所说的,我用了任何高深的编程技巧,没有什么编程技巧,就是一些常用的API函数,直接照API文档抄的,因为aardio调用外部API函数的语法是如此简单,所以一切很容易。


在写完 sys.printer 以后,我想试试用 sys.printer 来控制小票打印机,试了网上的一些范例都不成功,然后我找了条码打印机的一些SDK,发现不同厂商的SDK都是提供一个类似的TSCLIB.DLL,导出的接口基本都一样,而这个TSCLIB.DLL不知道出自何处,每个SDK里都没有说明,DLL的版权说明都是空的,好吧有可能是大家都复制了相同一份不知道谁随手写的代码,这个DLL的函数非常简单,用法也很简单,只有几个函数(这个DLL的文档我放到了 /lib/tsclib/.res目录下,引用了这个库就可以自动下载),而其他的函数我看了一下,大概内部的代码是简单的格式化字符串最后都调用 tsclib.sendcommand() 发送指令,我封装了一个tsclib扩展库,测试代码如下:

import console; 
import tsclib;

//这里需要改成你的条码打印机名称
tsclib.openport("Gprinter  GP-3120TU"); 
tsclib.setup("40","30","3","10","0","3","0");

//直接输出TSC-TSPL指令
tsclib.sendcommand("SET CUTTER OFF");
tsclib.sendcommand("DIRECTION 1");
tsclib.clearbuffer();

//打印条码
//tsclib.barcode("100","50","39","96","1","0","2","4","123456789");

//打印二维码
tsclib.qrcode("100","100","H","4","A","0","M2","S7","AABCB03abcN123汉字")
//tsclib.printerfont("100","200","TSS24.BF2","0","2","2","中文字体");

//直接输出TSPL指令
tsclib.sendcommand("BOX 50,10,600,280,5");
//tsclib.windowsfont(100,200,24,0,2,0,"arial","中文 Font 72 pt");
        
tsclib.printlabel("1","1");
tsclib.closeport();

console.pause(true);

用起来非常简单,测试成功,不知道为什么有人跟我说等了好几年在等控制小票打印机的扩展库 - 难道可以花好几年的时间等,却没有几分钟的时间看一下厂家提供的SDK什么的 ?!

TSCLIB使用的是TSPL指令语言,这个TSCLIB估计也是用WritePrinter这个API发送指令(也就是sys.printer里的write函数),理论上不通过TSCLIB组件也可以控制打印机,但没有找到相关资料,经过我的验证这个方法是可行的,只要注意一个规则:TSPL指令必须分行发送,每行指令尾部必须以'\r\n'结束,下面是测试代码:

import console; 
import sys.printer;

var pt = sys.printer("Gprinter  GP-3120TU");
pt.start(
    function(){
    pt.write('SIZE 40 mm,30 mm\r\n')
    pt.write('GAP 2 mm,0 mm\r\n')   
    pt.write('DENSITY 6\r\n')   
    pt.write('SPEED 5\r\n')     
    pt.write('DIRECTION 0\r\n')     
    pt.write('REFERENCE 0\r\n')     
    pt.write('CLS\r\n')     
    pt.write('TEXT 30,40 ,"1",0,2,2,"NO:4872"\r\n')
    pt.write('BARCODE 30,100,"128M",40,1,0,2,1,"69123888"\r\n') 
    pt.write('PRINT 1\r\n') 
    }
);

console.pause(true);

所以你看,一切都很简单,条条大路通罗马!如果不愿意动脑动手,那就只能不停的等待别人。每次我一说这话,就有一些人威胁说我的人品有毛病,其实我真的没有什么恶意。可能有那么一些人,喜欢把简单的代码或者技术说的非常麻烦 - 用于掩饰自己的问题。但aardio非常简单,aardio的“库”也都非常简单,很多人惊讶于aardio库函数的说明通常只有几句话 - 是的,一切都是那么简单。其实编程这个东西 - 90%最难用的东西我们90%的时候根本用不上,所以我在封装库函数的时候,通常只留下  10%最容易使用最常用的东西,就以上面的 sys.printer 为例,也许你去看打印机API的文档会让你吃惊有如此多的参数和用法,但你在使用 sys.printer的时候发现参数是如此的少,很多函数根本不要参数,这也是为什么aardio的库函数的参数说明、用法说明都极其简洁的原因,这也是为什么有人拿起aardio看几下就能用的很爽的原因( 当然我们不能否认,再简单的东西,总会有一堆人一边用一边叫苦,喜欢叫苦的人,无论给他什么他都用不好)。

引用自:http://mp.weixin.qq.com/s/_1LSDew3eNwRZopXa53I3A

aar中定义字符串为变量名

tab = {};
mainForm.button.oncommand = function(id,event){
for(i=1;5;1){
        var strname = "wbKitView" ++ tostring(i);
tab[strname] = i;
}

}

mainForm.button2.oncommand = function(id,event){
console.dump(tab)
}

blob.png


一个用custom控件调用webkit使用的界面

import win.ui;
/*DSG{{*/
mainForm = win.form(text="webkit浏览器支持库";right=748;bottom=485;border="dialog frame";mode="popup")
mainForm.add(
custom={cls="custom";text="custom";left=218;top=135;right=353;bottom=174;clip=1;transparent=1;z=1};
custom2={cls="custom";text="custom2";left=359;top=319;right=494;bottom=358;clip=1;transparent=1;z=2};
custom3={cls="custom";text="custom3";left=359;top=136;right=495;bottom=176;clip=1;transparent=1;z=3};
custom4={cls="custom";text="custom4";left=218;top=317;right=353;bottom=356;clip=1;transparent=1;z=4};
custom5={cls="custom";text="custom5";left=359;top=228;right=494;bottom=267;clip=1;transparent=1;z=5};
custom6={cls="custom";text="custom6";left=359;top=46;right=494;bottom=85;clip=1;transparent=1;z=6};
custom7={cls="custom";text="custom7";left=218;top=226;right=352;bottom=265;clip=1;transparent=1;z=7};
custom8={cls="custom";text="custom8";left=218;top=44;right=353;bottom=83;clip=1;transparent=1;z=8};
custom9={cls="custom";text="custom9";left=18;top=22;right=214;bottom=415;ah=1;z=9}
)
/*}}*/

//导入webkit支持库
import web.kit.form;
import web.kit.jsFunction;
//import console;
//console.open();

import wsock.tcp.simpleHttpServer;
tab = {};


for(name,ctrl in mainForm.eachControl("custom") ){
        var i=1;
       // console.log(name,ctrl);
        var strname = "wbKitView" ++ tostring(i);
        if(name != "custom9"){
                tab[strname] = web.kit.form(mainForm[name]);//创建webkit浏览器窗口
     tab[strname].go( wsock.tcp.simpleHttpServer.startUrl("/html/main.aardio") ); 
     i++;
        }

}

 wbKitView = web.kit.form(mainForm.custom9);//创建webkit浏览器窗口
     wbKitView.go( wsock.tcp.simpleHttpServer.startUrl("/html/cebian.aardio") );



/*
//使用external接口定义网页脚本可调用的本地函数
wbKitView.external = {

    aardioCall = function(str){ 
        mainForm.msgbox(str);
    };
}
*/

/**
//打开链接时触发
wbKitView.onNavigation = function(url,navigationType){ 
if( navigationType == 0/*_WKE_NAVIGATION_TYPE_LINKCLICK*/ ){

}
return true;
}
**/




//可以使用CSS选择器获取HTML节点对象
//wbKitView.querySelector("#header .title-bar .title").innerText = "我 的 软 件";

//添加可拖动边框
import win.ui.resizeBorder;
win.ui.resizeBorder(mainForm);

//添加阴影
import win.ui.shadow;
win.ui.shadow(mainForm);

//限定最大化范围
import win.ui.minmax;
win.ui.minmax(mainForm);

mainForm.show();
win.loopMessage();
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<link rel="stylesheet" href="/html/layui/css/layui.css">
<script src="/html/layui/layui.js"></script>
<style type="text/css">
#main {  height:100% ; width:100%; position:absolute;}
body {  margin:0px; padding:0px; overflow:hidden;}
</style>
</head>
<body>
    <div id="main">
<div class="layui-side layui-bg-black">
    <div class="layui-side-scroll">
      <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
      <ul class="layui-nav layui-nav-tree"  lay-filter="test">
        <li class="layui-nav-item layui-nav-itemed">
          <a class="" href="javascript:;">所有商品</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">列表一</a></dd>
            <dd><a href="javascript:;">列表二</a></dd>
            <dd><a href="javascript:;">列表三</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item">
          <a href="javascript:;">解决方案</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">列表一</a></dd>
            <dd><a href="javascript:;">列表二</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item"><a href="">云市场</a></li>
        <li class="layui-nav-item"><a href="">发布商品</a></li>
      </ul>
    </div>
  </div>
    </div> 
<script>
//JavaScript代码区域
layui.use('element', function(){
  var element = layui.element;
  
});
</script>
</body>
</html>

blob.png

aar调用摄像头1:

import win.ui;
/*DSG{{*/
var winform = win.form(parent=...; right=471;text="aardio Form";bottom=360 )
winform.add( 
button2={ bottom=348;right=305;left=176;top=313;font=LOGFONT( name="SimSun";h=-12 );z=2;text="关闭";cls="button" };
button={ bottom=347;text="开启";left=331;top=312;font=LOGFONT( name="SimSun";h=-12 );z=1;right=460;cls="button" }
)
/*}}*/


 ::Avicap32 := ..raw.loadDll("Avicap32.dll")
capCreateCaptureWindow = ::Avicap32.api("capCreateCaptureWindowA","int(string lpszWindowName,int dwStyle,int X,int Y,int nWidth,int nHeight,int hwndParent,int nID)")

WM_CAP_START = 0x400;
WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10;
WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11;
WM_CAP_SET_OVERLAY = WM_CAP_START + 51;
WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52
WM_CAP_SET_PREVIEW = WM_CAP_START + 50

winform.button.oncommand = function(id,event){
        //建立捕获窗口
        nStyle = 0x40000000+0x10000000
        CapHwnd = capCreateCaptureWindow("摄像头0", nStyle, 0, 0, 400 , 300, winform.hwnd,1)
        //建立捕获窗口到捕获设备的连接
        ::PostMessage(CapHwnd, WM_CAP_DRIVER_CONNECT ,0 ,0);
        
        win.delay(1000)
        //设置捕获的帧频率为30毫秒一帧
        ::PostMessage(CapHwnd, WM_CAP_SET_PREVIEWRATE, 10,0);

        ::PostMessage(CapHwnd, WM_CAP_SET_OVERLAY, 1,0);
        //用预览模式在捕获窗口开始预览图像
        ::PostMessage(CapHwnd, WM_CAP_SET_PREVIEW, 1,0);
}


winform.button2.oncommand = function(id,event){
        ::PostMessage(CapHwnd, WM_CAP_DRIVER_DISCONNECT, 0,0);
        CapHwnd= null;
}



winform.show() 
win.loopMessage();

blob.png

列出电脑中所有的摄像头设备:

上述代码中增加capGetDriverDescription()函数

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio Form";right=471;bottom=360;parent=...)
winform.add(
button={cls="button";text="开启";left=331;top=312;right=460;bottom=347;font=LOGFONT(name='SimSun');z=1};
button2={cls="button";text="关闭";left=176;top=313;right=305;bottom=348;font=LOGFONT(name='SimSun');z=2};
button3={cls="button";text="枚举";left=22;top=313;right=151;bottom=348;font=LOGFONT(name='SimSun');z=3}
)
/*}}*/




::Avicap32 := ..raw.loadDll("Avicap32.dll")
capCreateCaptureWindow = ::Avicap32.api("capCreateCaptureWindowA","int(string lpszWindowName,int dwStyle,int X,int Y,int nWidth,int nHeight,int hwndParent,int nID)")
capGetDriverDescription = ::Avicap32.api("capGetDriverDescriptionA","bool(word wDriver,str &lpszName,int cbName,str &lpszVer,int cbVer)");
WM_CAP_START = 0x400;
WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10;
WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11;
WM_CAP_SET_OVERLAY = WM_CAP_START + 51;
WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52
WM_CAP_SET_PREVIEW = WM_CAP_START + 50

winform.button.oncommand = function(id,event){
        //建立捕获窗口
        nStyle = 0x40000000+0x10000000
        CapHwnd = capCreateCaptureWindow("摄像头0", nStyle, 0, 0, 800 , 600, winform.hwnd,1)
        //建立捕获窗口到捕获设备的连接
        ::PostMessage(CapHwnd, WM_CAP_DRIVER_CONNECT ,0 ,0);
        
        win.delay(1000)
        //设置捕获的帧频率为30毫秒一帧
        ::PostMessage(CapHwnd, WM_CAP_SET_PREVIEWRATE, 5,0);

        ::PostMessage(CapHwnd, WM_CAP_SET_OVERLAY, 1,0);
        //用预览模式在捕获窗口开始预览图像
        ::PostMessage(CapHwnd, WM_CAP_SET_PREVIEW, 1,0);
}


winform.button2.oncommand = function(id,event){
        ::PostMessage(CapHwnd, WM_CAP_DRIVER_DISCONNECT, 0,0);
        CapHwnd= null;
}
winform.button3.oncommand = function(id,event){

io.open()
for(wDriverIndex=0;9){
     var ok,name,ver = capGetDriverDescription(wDriverIndex,80,80,80,80) 
     if(ok){
       io.print(wDriverIndex,name,ver)
       //用上面的代码列出所有设备,其中wDriverIndex作为capCreateCaptureWindow的最后一个参数。
//你也可以添加到列表中,让用户选择。
     } 
}
}


winform.show() 
win.loopMessage();

blob.png

(转)aar操作摄像头完整示例:

import win.ui;
import win.ui.ctrl.afvideocapture;
/*DSG{{*/
var winform = ..win.form( right=614;bottom=487;parent=...;text="视频捕获控件";border="resizable" )
winform.add( 
afvideocapture={ dr=1;dl=1;bottom=440;right=608;left=8;dt=1;top=8;font=LOGFONT( name='SimSun' );z=1;db=1;transparent=1;cls="afvideocapture" };
btnScale={ dl=1;bottom=472;right=400;left=312;top=448;font=LOGFONT( name='SimSun' );z=5;db=1;text="缩放模式";cls="button" };
btnConnect={ dl=1;bottom=472;right=192;left=104;top=448;font=LOGFONT( name='SimSun' );z=3;db=1;text="连接设备";cls="button" };
btnPreview={ dl=1;bottom=472;right=496;left=408;top=448;font=LOGFONT( name='SimSun' );z=6;db=1;text="预览模式";cls="button" };
btnEnumDrivers={ dl=1;bottom=472;text="枚举设备";left=8;top=448;font=LOGFONT( name='SimSun' );z=2;db=1;right=96;cls="button" };
btnDisconnect={ dl=1;bottom=472;text="断开设备连接";left=200;top=448;font=LOGFONT( name='SimSun' );z=4;db=1;right=304;cls="button" };
btnSave={ dl=1;bottom=472;right=592;left=504;top=448;font=LOGFONT( name='SimSun' );z=7;db=1;text="保存截图";cls="button" }
)
/*}}*/

winform.btnEnumDrivers.oncommand = function(id,event){
    io.open();
    io.print("视频设备有:");
    
    for (i = 0; 9) {
        var name, ver = winform.afvideocapture.getDriverDescription(i);
        if ( ! name) break;
        
        io.print(name, ver);
    }
}

winform.btnConnect.oncommand = function(id,event){
    winform.afvideocapture.driverConnect(0);
}

winform.btnDisconnect.oncommand = function(id,event){
    winform.afvideocapture.driverDisconnect();
}

winform.btnScale.oncommand = function(id,event){
    winform.afvideocapture.setScale(true);
}

winform.btnPreview.oncommand = function(id,event){
    winform.afvideocapture.setPreviewRate(30); // 30ms 一帧
    winform.afvideocapture.setPreview(true);
}

winform.btnSave.oncommand = function(id,event){
    import process;
    var tmp = io.tmpname() + ".bmp";
    winform.afvideocapture.fileSaveDIB(tmp);
    process.execute(tmp);
}

winform.show() 
win.loopMessage();

运行上面的代码,如果没安装过这个摄像头库,会提示下载。下面是支持库的源码:

/*
Author: lujjjh
Date:   2011-9-4
*/

import win.ui.ctrl.static;

namespace win.ui.ctrl; 

class afvideocapture { 
ctor(parent,tvalue) {
tvalue.cls = "static";
this = ..win.ui.ctrl.static(parent, tvalue);
}

onCreate = function () {
this.hwndControl = capCreateCaptureWindow(, 0x10000000 | 0x40000000/*_WS_VISIBLE | _WS_CHILD*/, 0, 0, this.clientRect.right, this.clientRect.bottom, this.hwnd, 1);
this.wndproc = function (hwnd, message, wParam, lParam) {
if (message == 0x5/*_WM_SIZE*/) {
..win.setPos(this.hwndControl, 0, 0, this.clientRect.right, this.clientRect.bottom);
}
}
}

onDestroy = function () {
::DestroyWindow(this.hwndControl);
}

// Basic Capture Operations
abort = function () {
return ::SendMessageInt(this.hwndControl, 0x445/*_WM_CAP_ABORT*/, 0, 0);
}

driverConnect = function (index = 0) {
return ::SendMessageInt(this.hwndControl, 0x40A/*_WM_CAP_DRIVER_CONNECT*/, index, 0);
}

sequence = function () {
return ::SendMessageInt(this.hwndControl, 0x43E/*_WM_CAP_SEQUENCE*/, 0, 0);
}

stop = function () {
return ::SendMessageInt(this.hwndControl, 0x444/*_WM_CAP_STOP*/, 0, 0);
}

// Capture Windows
getDriverDescription = function (index) {
var re, name, ver = capGetDriverDescription(index, 128, 128, 128, 128);
if (re) {
return ..string.str(name), ..string.str(ver);
}
else {
return null, null, ..lasterr();
}
}

driverDisconnect = function () {
return ::SendMessageInt(this.hwndControl, 0x40B/*_WM_CAP_DRIVER_DISCONNECT*/, 0, 0);
}

getStatus = function () {
var status = CAPSTATUS();
::SendMessageByStruct(this.hwndControl, 0x436/*_WM_CAP_GET_STATUS*/, ..raw.sizeof(status), status);
return status;
}

// Capture Drivers
driverGetCaps = function () {
var driverCaps = CAPDRIVERCAPS();
::SendMessageByStruct(this.hwndControl, 0x40E/*_WM_CAP_DRIVER_GET_CAPS*/, ..raw.sizeof(driverCaps), driverCaps);
return driverCaps;
}

driverGetName = function () {
var re, name = ::SendMessageByString(this.hwndControl, 0x40C/*_WM_CAP_DRIVER_GET_NAME*/, 128, 128);
if (re) {
return ..string.str(name);
}
else {
return null, ..lasterr();
}
}

driverGetVersion = function () {
var re, ver = ::SendMessageByString(this.hwndControl, 0x40D/*_WM_CAP_DRIVER_GET_VERSION*/, 128, 128);
if (re) {
return ..string.str(ver);
}
else {
return null, ..lasterr();
}
}

driverGetAudioFormat = function () {
var format = WAVEFORMATEX();
::SendMessageByStruct(this.hwndControl, 0x424/*_WM_CAP_GET_AUDIOFORMAT*/, ..raw.sizeof(format), format);
return format;
}

driverGetVideoFormat = function () {
var format = BITMAPINFO();
::SendMessageByStruct(this.hwndControl, 0x42C/*_WM_CAP_GET_VIDEOFORMAT*/, ..raw.sizeof(format), format);
return format;
}

driverSetAudioFormat = function (format) {
return ::SendMessageByStruct(this.hwndControl, 0x423/*_WM_CAP_SET_AUDIOFORMAT*/, ..raw.sizeof(format), format);
}

driverSetVideoFormat = function (format) {
return ::SendMessageByStruct(this.hwndControl, 0x42D/*_WM_CAP_SET_VIDEOFORMAT*/, ..raw.sizeof(format), format);
}

// Capture Driver Preview and Overlay Modes
setOverlay = function (bOverlay) {
return ::SendMessageInt(this.hwndControl, 0x433/*_WM_CAP_SET_OVERLAY*/, bOverlay ? 1 : 0, 0);
}

setPreview = function (bPreview) {
return ::SendMessageInt(this.hwndControl, 0x432/*_WM_CAP_SET_PREVIEW*/, bPreview ? 1 : 0, 0);
}

setPreviewRate = function (rate) {
return ::SendMessageInt(this.hwndControl, 0x434/*_WM_CAP_SET_PREVIEWRATE*/, rate, 0);
}

setScale = function (bScale) {
return ::SendMessageInt(this.hwndControl, 0x435/*_WM_CAP_SET_SCALE*/, bScale ? 1 : 0, 0);
}

setScroll = function (x, y) {
var pt = ::POINT(x, y);
return ::SendMessageByStruct(this.hwndControl, 0x437/*_WM_CAP_SET_SCROLL*/, 0, pt);
}

// Capture Driver Video Dialog Boxes
dlgVideoCompression = function () {
return ::SendMessageInt(this.hwndControl, 0x42E/*_WM_CAP_DLG_VIDEOCOMPRESSION*/, 0, 0);
}

dlgVideoDisplay = function () {
return ::SendMessageInt(this.hwndControl, 0x42B/*_WM_CAP_DLG_VIDEODISPLAY*/, 0, 0);
}

dlgVideoFormat = function () {
return ::SendMessageInt(this.hwndControl, 0x429/*_WM_CAP_DLG_VIDEOFORMAT*/, 0, 0);
}

dlgVideoSource = function () {
return ::SendMessageInt(this.hwndControl, 0x42A/*_WM_CAP_DLG_VIDEOSOURCE*/, 0, 0);
}

// Video Capture Settings
getSequenceSetup = function () {
var params = CAPTUREPARMS();
::SendMessageByStruct(this.hwndControl, 0x441/*_WM_CAP_GET_SEQUENCE_SETUP*/, ..raw.sizeof(params), params);
return params;
}

setSequenceSetup = function (params) {
return ::SendMessageByStruct(this.hwndControl, 0x440/*_WM_CAP_SET_SEQUENCE_SETUP*/, ..raw.sizeof(params), params);
}

// Capture File and Buffers
fileAllocate = function (size) {
return ::SendMessageInt(this.hwndControl, 0x416/*_WM_CAP_FILE_ALLOCATE*/, 0, size);
}

fileGetCaptureFile = function () {
var re, name = ::SendMessageByString(this.hwndControl, 0x415/*_WM_CAP_FILE_GET_CAPTURE_FILE*/, 0x104/*_MAX_PATH*/, 0x104/*_MAX_PATH*/);
if (re) {
return ..string.str(name);
}
else {
return null, ..lasterr();
}
}

fileSaveAs = function (name) {
return ::SendMessage(this.hwndControl, 0x417/*_WM_CAP_FILE_SAVEAS*/, null, name);
}

fileSetCaptureFile = function (name) {
return ::SendMessage(this.hwndControl, 0x414/*_WM_CAP_FILE_SET_CAPTURE_FILE*/, null, name);
}

// Directly Using Capture Data
sequenceNoFile = function () {
return ::SendMessageInt(this.hwndControl, 0x43F/*_WM_CAP_SEQUENCE_NOFILE*/, 0, 0);
}

setMCIDevice = function (name) {
return ::SendMessage(this.hwndControl, 0x442/*_WM_CAP_SET_MCI_DEVICE*/, null, name);
}

// Manual Frame Capture
singleFrame = function () {
return ::SendMessageInt(this.hwndControl, 0x448/*_WM_CAP_SINGLE_FRAME*/, 0, 0);
}

singleFrameClose = function () {
return ::SendMessageInt(this.hwndControl, 0x447/*_WM_CAP_SINGLE_FRAME_CLOSE*/, 0, 0);
}

singleFrameOpen = function () {
return ::SendMessageInt(this.hwndControl, 0x446/*_WM_CAP_SINGLE_FRAME_OPEN*/, 0, 0);
}

// Still-Image Capture
editCopy = function () {
return ::SendMessageInt(this.hwndControl, 0x41E/*_WM_CAP_EDIT_COPY*/, 0, 0);
}

fileSaveDIB = function (name) {
return ::SendMessage(this.hwndControl, 0x419/*_WM_CAP_FILE_SAVEDIB*/, null, name);
}

grabFrame = function () {
return ::SendMessageInt(this.hwndControl, 0x43C/*_WM_CAP_GRAB_FRAME*/, 0, 0);
}

grabFrameNoStop = function () {
return ::SendMessageInt(this.hwndControl, 0x43D/*_WM_CAP_GRAB_FRAME_NOSTOP*/, 0, 0);
}

// Advanced Capture Options
// ...

// Working with Palettes
// ...

// Yielding to Other Applications
// ...

// AVICap Callback Functions
// ...

// More Information: http://msdn.microsoft.com/en-us/library/dd757696(v=vs.85).aspx
}

namespace afvideocapture {
var avicap32 = ..raw.loadDll("Avicap32.dll");
capCreateCaptureWindow = avicap32.api("capCreateCaptureWindowA", "int(string,INT,int,int,int,int,int,int)");
capGetDriverDescription = avicap32.api("capGetDriverDescriptionA", "int(word,string&,int,string&,int)");

CAPSTATUS = class {
INT uiImageWidth;
INT uiImageHeight;
int fLiveWindow;
int fOverlayWindow;
int fScale;
struct ptScroll = ::POINT();
int fUsingDefaultPalette;
int fAudioHardware;
int fCapFileExists;
INT dwCurrentVideoFrame;
INT dwCurrentVideoFramesDropped;
INT dwCurrentWaveSamples;
INT dwCurrentTimeElapsedMS;
pointer hPalCurrent;
int fCapturingNow;
INT dwReturn;
INT wNumVideoAllocated;
INT wNumAudioAllocated;
}

CAPDRIVERCAPS = class {
INT wDeviceIndex;
int fHasOverlay;
int fHasDlgVideoSource;
int fHasDlgVideoFormat;
int fHasDlgVideoDisplay;
int fCaptureInitialized;
int fDriverSuppliesPalettes;
int hVideoIn;
int hVideoOut;
int hVideoExtIn;
int hVideoExtOut;
}

WAVEFORMATEX = class {
WORD wFormatTag;
WORD nChannels;
INT nSamplesPerSec;
INT nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
}

BITMAPINFOHEADER = class {
INT biSize;
int biWidth;
int biHeight;
WORD biPlanes;
WORD biBitCount;
INT biCompression;
INT biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
INT biClrUsed;
INT biClrImportant;
}

RGBQUAD = class {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}

BITMAPINFO = class {
  struct bmiHeader = ..win.ui.ctrl.afvideocapture.BITMAPINFOHEADER();
  struct bmiColors[1] = { ..win.ui.ctrl.afvideocapture.RGBQUAD() };
}

CAPTUREPARMS = class {
INT dwRequestMicroSecPerFrame;
int fMakeUserHitOKToCapture;
INT wPercentDropForError;
int fYield;
INT dwIndexSize;
INT wChunkGranularity;
int fUsingDOSMemory;
INT wNumVideoRequested;
int fCaptureAudio;
INT wNumAudioRequested;
INT vKeyAbort;
int fAbortLeftMouse;
int fAbortRightMouse;
int fLimitEnabled;
INT wTimeLimit;
int fMCIControl;
int fStepMCIDevice;
INT dwMCIStartTime;
INT dwMCIStopTime;
int fStepCaptureAt2x;
INT wStepCaptureAverageFrames;
INT dwAudioBufferSize;
int fDisableWriteCache;
INT AVStreamMaster;
}
}

/**intellisense()
win.ui.ctrl.afcapture = 视频捕获控件
?win.ui.ctrl.afcapture = !afcapture.

!afcapture.abort() = 
!afcapture.driverConnect(__/*设备索引*/) = 连接设备
!afcapture.sequence() = 
!afcapture.stop() = 
!afcapture.getDriverDescription(__/*设备索引*/) = 
!afcapture.driverDisconnect() = 断开连接设备
!afcapture.getStatus() = 
!afcapture.driverGetCaps() = 
!afcapture.driverGetName() = 
!afcapture.driverGetVersion() = 
!afcapture.driverGetAudioFormat() = 
!afcapture.driverGetVideoFormat() = 
!afcapture.driverSetAudioFormat(__/*音频格式*/) = 
!afcapture.driverSetVideoFormat(__/*视频格式*/) = 
!afcapture.setOverlay(__/*是否开启覆盖模式*/) = 
!afcapture.setPreview(__/*是否开启预览模式*/) = 
!afcapture.setPreviewRate(__/*预览频率*/) = 
!afcapture.setScale(__/*是否自动缩放*/) = 
!afcapture.setScroll(.(x,y) = 
!afcapture.dlgVideoCompression() = 
!afcapture.dlgVideoDisplay() = 
!afcapture.dlgVideoFormat() = 
!afcapture.dlgVideoSource() = 
!afcapture.getSequenceSetup() = 
!afcapture.setSequenceSetup(__/*参数*/) = 
!afcapture.fileAllocate(__/*预分配大小*/) = 
!afcapture.fileGetCaptureFile() = 
!afcapture.fileSaveAs(__/*文件名*/) = 
!afcapture.fileSetCaptureFile(__/*文件名*/) = 
!afcapture.sequenceNoFile() = 
!afcapture.setMCIDevice(__/*设备名称*/) = 
!afcapture.singleFrame() = 
!afcapture.singleFrameClose() = 
!afcapture.singleFrameOpen() = 
!afcapture.editCopy() = 
!afcapture.fileSaveDIB(__/*文件名*/) = 
!afcapture.grabFrame() = 
!afcapture.grabFrameNoStop() = 
end intellisense**/


 /**intellisense()
_WM_CAP_START=@0x400/*_WM_CAP_START*/
_WM_CAP_UNICODE_START=@0x464/*_WM_CAP_UNICODE_START*/
_WM_CAP_GET_CAPSTREAMPTR=@0x401/*_WM_CAP_GET_CAPSTREAMPTR*/
_WM_CAP_SET_CALLBACK_ERRORW=@0x466/*_WM_CAP_SET_CALLBACK_ERRORW*/
_WM_CAP_SET_CALLBACK_STATUSW=@0x467/*_WM_CAP_SET_CALLBACK_STATUSW*/
_WM_CAP_SET_CALLBACK_ERRORA=@0x402/*_WM_CAP_SET_CALLBACK_ERRORA*/
_WM_CAP_SET_CALLBACK_STATUSA=@0x403/*_WM_CAP_SET_CALLBACK_STATUSA*/
_WM_CAP_SET_CALLBACK_ERROR=@0x402/*_WM_CAP_SET_CALLBACK_ERROR*/
_WM_CAP_SET_CALLBACK_STATUS=@0x403/*_WM_CAP_SET_CALLBACK_STATUS*/
_WM_CAP_SET_CALLBACK_YIELD=@0x404/*_WM_CAP_SET_CALLBACK_YIELD*/
_WM_CAP_SET_CALLBACK_FRAME=@0x405/*_WM_CAP_SET_CALLBACK_FRAME*/
_WM_CAP_SET_CALLBACK_VIDEOSTREAM=@0x406/*_WM_CAP_SET_CALLBACK_VIDEOSTREAM*/
_WM_CAP_SET_CALLBACK_WAVESTREAM=@0x407/*_WM_CAP_SET_CALLBACK_WAVESTREAM*/
_WM_CAP_GET_USER_DATA=@0x408/*_WM_CAP_GET_USER_DATA*/
_WM_CAP_SET_USER_DATA=@0x409/*_WM_CAP_SET_USER_DATA*/
_WM_CAP_DRIVER_CONNECT=@0x40A/*_WM_CAP_DRIVER_CONNECT*/
_WM_CAP_DRIVER_DISCONNECT=@0x40B/*_WM_CAP_DRIVER_DISCONNECT*/
_WM_CAP_DRIVER_GET_NAMEA=@0x40C/*_WM_CAP_DRIVER_GET_NAMEA*/
_WM_CAP_DRIVER_GET_VERSIONA=@0x40D/*_WM_CAP_DRIVER_GET_VERSIONA*/
_WM_CAP_DRIVER_GET_NAMEW=@0x470/*_WM_CAP_DRIVER_GET_NAMEW*/
_WM_CAP_DRIVER_GET_VERSIONW=@0x471/*_WM_CAP_DRIVER_GET_VERSIONW*/
_WM_CAP_DRIVER_GET_NAME=@0x40C/*_WM_CAP_DRIVER_GET_NAME*/
_WM_CAP_DRIVER_GET_VERSION=@0x40D/*_WM_CAP_DRIVER_GET_VERSION*/
_WM_CAP_DRIVER_GET_CAPS=@0x40E/*_WM_CAP_DRIVER_GET_CAPS*/
_WM_CAP_FILE_SET_CAPTURE_FILEA=@0x414/*_WM_CAP_FILE_SET_CAPTURE_FILEA*/
_WM_CAP_FILE_GET_CAPTURE_FILEA=@0x415/*_WM_CAP_FILE_GET_CAPTURE_FILEA*/
_WM_CAP_FILE_SAVEASA=@0x417/*_WM_CAP_FILE_SAVEASA*/
_WM_CAP_FILE_SAVEDIBA=@0x419/*_WM_CAP_FILE_SAVEDIBA*/
_WM_CAP_FILE_SET_CAPTURE_FILEW=@0x478/*_WM_CAP_FILE_SET_CAPTURE_FILEW*/
_WM_CAP_FILE_GET_CAPTURE_FILEW=@0x479/*_WM_CAP_FILE_GET_CAPTURE_FILEW*/
_WM_CAP_FILE_SAVEASW=@0x47B/*_WM_CAP_FILE_SAVEASW*/
_WM_CAP_FILE_SAVEDIBW=@0x47D/*_WM_CAP_FILE_SAVEDIBW*/
_WM_CAP_FILE_SAVEAS=@0x417/*_WM_CAP_FILE_SAVEAS*/
_WM_CAP_FILE_SAVEDIB=@0x419/*_WM_CAP_FILE_SAVEDIB*/
_WM_CAP_FILE_SET_CAPTURE_FILE=@0x414/*_WM_CAP_FILE_SET_CAPTURE_FILE*/
_WM_CAP_FILE_GET_CAPTURE_FILE=@0x415/*_WM_CAP_FILE_GET_CAPTURE_FILE*/
_WM_CAP_FILE_ALLOCATE=@0x416/*_WM_CAP_FILE_ALLOCATE*/
_WM_CAP_FILE_SET_INFOCHUNK=@0x418/*_WM_CAP_FILE_SET_INFOCHUNK*/
_WM_CAP_EDIT_COPY=@0x41E/*_WM_CAP_EDIT_COPY*/
_WM_CAP_SET_AUDIOFORMAT=@0x423/*_WM_CAP_SET_AUDIOFORMAT*/
_WM_CAP_GET_AUDIOFORMAT=@0x424/*_WM_CAP_GET_AUDIOFORMAT*/
_WM_CAP_DLG_VIDEOFORMAT=@0x429/*_WM_CAP_DLG_VIDEOFORMAT*/
_WM_CAP_DLG_VIDEOSOURCE=@0x42A/*_WM_CAP_DLG_VIDEOSOURCE*/
_WM_CAP_DLG_VIDEODISPLAY=@0x42B/*_WM_CAP_DLG_VIDEODISPLAY*/
_WM_CAP_GET_VIDEOFORMAT=@0x42C/*_WM_CAP_GET_VIDEOFORMAT*/
_WM_CAP_SET_VIDEOFORMAT=@0x42D/*_WM_CAP_SET_VIDEOFORMAT*/
_WM_CAP_DLG_VIDEOCOMPRESSION=@0x42E/*_WM_CAP_DLG_VIDEOCOMPRESSION*/
_WM_CAP_SET_PREVIEW=@0x432/*_WM_CAP_SET_PREVIEW*/
_WM_CAP_SET_OVERLAY=@0x433/*_WM_CAP_SET_OVERLAY*/
_WM_CAP_SET_PREVIEWRATE=@0x434/*_WM_CAP_SET_PREVIEWRATE*/
_WM_CAP_SET_SCALE=@0x435/*_WM_CAP_SET_SCALE*/
_WM_CAP_GET_STATUS=@0x436/*_WM_CAP_GET_STATUS*/
_WM_CAP_SET_SCROLL=@0x437/*_WM_CAP_SET_SCROLL*/
_WM_CAP_GRAB_FRAME=@0x43C/*_WM_CAP_GRAB_FRAME*/
_WM_CAP_GRAB_FRAME_NOSTOP=@0x43D/*_WM_CAP_GRAB_FRAME_NOSTOP*/
_WM_CAP_SEQUENCE=@0x43E/*_WM_CAP_SEQUENCE*/
_WM_CAP_SEQUENCE_NOFILE=@0x43F/*_WM_CAP_SEQUENCE_NOFILE*/
_WM_CAP_SET_SEQUENCE_SETUP=@0x440/*_WM_CAP_SET_SEQUENCE_SETUP*/
_WM_CAP_GET_SEQUENCE_SETUP=@0x441/*_WM_CAP_GET_SEQUENCE_SETUP*/
_WM_CAP_SET_MCI_DEVICEA=@0x442/*_WM_CAP_SET_MCI_DEVICEA*/
_WM_CAP_GET_MCI_DEVICEA=@0x443/*_WM_CAP_GET_MCI_DEVICEA*/
_WM_CAP_SET_MCI_DEVICEW=@0x4A6/*_WM_CAP_SET_MCI_DEVICEW*/
_WM_CAP_GET_MCI_DEVICEW=@0x4A7/*_WM_CAP_GET_MCI_DEVICEW*/
_WM_CAP_SET_MCI_DEVICE=@0x442/*_WM_CAP_SET_MCI_DEVICE*/
_WM_CAP_GET_MCI_DEVICE=@0x443/*_WM_CAP_GET_MCI_DEVICE*/
_WM_CAP_STOP=@0x444/*_WM_CAP_STOP*/
_WM_CAP_ABORT=@0x445/*_WM_CAP_ABORT*/
_WM_CAP_SINGLE_FRAME_OPEN=@0x446/*_WM_CAP_SINGLE_FRAME_OPEN*/
_WM_CAP_SINGLE_FRAME_CLOSE=@0x447/*_WM_CAP_SINGLE_FRAME_CLOSE*/
_WM_CAP_SINGLE_FRAME=@0x448/*_WM_CAP_SINGLE_FRAME*/
_WM_CAP_PAL_OPENA=@0x450/*_WM_CAP_PAL_OPENA*/
_WM_CAP_PAL_SAVEA=@0x451/*_WM_CAP_PAL_SAVEA*/
_WM_CAP_PAL_OPENW=@0x4B4/*_WM_CAP_PAL_OPENW*/
_WM_CAP_PAL_SAVEW=@0x4B5/*_WM_CAP_PAL_SAVEW*/
_WM_CAP_PAL_OPEN=@0x450/*_WM_CAP_PAL_OPEN*/
_WM_CAP_PAL_SAVE=@0x451/*_WM_CAP_PAL_SAVE*/
_WM_CAP_PAL_PASTE=@0x452/*_WM_CAP_PAL_PASTE*/
_WM_CAP_PAL_AUTOCREATE=@0x453/*_WM_CAP_PAL_AUTOCREATE*/
_WM_CAP_PAL_MANUALCREATE=@0x454/*_WM_CAP_PAL_MANUALCREATE*/
_WM_CAP_SET_CALLBACK_CAPCONTROL=@0x455/*_WM_CAP_SET_CALLBACK_CAPCONTROL*/
_WM_CAP_UNICODE_END=@0x4B5/*_WM_CAP_UNICODE_END*/
_WM_CAP_END=@0x4B5/*_WM_CAP_END*/
end intellisense**/

blob.png

转自:http://bbs.aardio.com/forum.php/forum.php?mod=viewthread&tid=2992

不保存生成的二维码为图片,而直接使用的方法:

//生成测试二维码
import qrencode.bitmap;
var qrBmp = qrencode.bitmap("http://www.stm32cube.com/#Stm32cube中文网222" );
//主要利用copyBitmapString()缩放为指定大小的GDI+位图,并返回图像数据
//获取生成的图像数据
var tutu = qrBmp.copyBitmapString(100,"*.bmp");
  
//识别二维码    
import zbar;
import soImage; //此扩展库要使用最新版
 
var img = soImage();
//setBytes(.(数据,"*->bmp") = 修改图像数据,\n参数一为字符串对象
img.setBytes(tutu,"*.bmp");
img.grayScale();//修改为灰度图
//img.save("/test.jpg");//可以保存下来看看图像
     
scanner = zbar.scanner();
scanner.config('qrcode.enable');//可省略
 
import console;
//图像数据,图像宽度,高度
scanner.scan(img.getData(),img.getWidth(),img.getHeight(),function(typeName,data){
        console.log(typeName,data)
    })

      
     
console.pause();


将摄像头完整应用程序中保存截图命令更改为捕获帧图像功能:

winform.btnSave.oncommand = function(id,event){

import soImage; //此扩展库要使用最新版

var img = soImage();
//不停止图像帧的情况下获取一帧静态图像
  winform.afvideocapture.grabFrameNoStop();
  //将获取到的图像数据复制到剪切板
  winform.afvideocapture.editCopy();
  //从剪切板获取图像数据
  img.fromClipBD();
  //灰度变换
  img.grayScale();
  //保存图像数据,以便观察
  img.save("/test.jpg");

 
}

为以后调用二维码扫描做准备。。。。

但是发现 那个zbar库,貌似得不到数据,不知道哪里出错了?。。。。。

调用笔记本摄像头扫描二维码:

目前不知道是摄像头不够清晰或者反光问题,有时候就是扫描不到,摆正或者倾斜应该都可以扫描到,

还有很奇怪的一点:我用自己生成的二维码就不好用,用网上搜索的二维码就好用多了。。。晕

 import console;
 console.open();
winform.btnSave.oncommand = function(id,event){

import soImage; //此扩展库要使用最新版
import zbar;
var img = soImage();
//不停止图像帧的情况下获取一帧静态图像
  winform.afvideocapture.grabFrameNoStop();
  //将获取到的图像数据复制到剪切板
  winform.afvideocapture.editCopy();
  //从剪切板获取图像数据
  img.fromClipBD();
  //灰度变换
  img.grayScale();
  //保存图像数据,以便观察
  //img.save("/test.jpg");


scanner = zbar.scanner();
scanner.config('qrcode.enable');//可省略
 
scanner.scan(img.getData(),img.getWidth(),img.getHeight(),function(typeName,data){

         console.log(typeName,data)
     })
      
}

blob.png

查找一个屏幕上给定的点是不是在矩形范围内:PtInRect()

listbox的hitTest函数使用了此方法判断

hitTest = function(x,y,screen=false){
if( !(x && y) ){
x,y = ..win.getMessagePos();
screen = true;

if(screen) x,y = ..win.toClient(owner.hwnd,x,y)
//遍历所有的列表项,看点是否在之内
var rc = ::RECT();
for(i=1;owner.count;1){
if(! owner.getItemRect(i,rc) ) return; 
if( ::PtInRect(rc,x,y) )
return i; 

};

这个PtInRect()方法可以用到自定义区域产生右键彩蛋上。

获取网络上图片,经过GDI处理后保存到本地:

import process; 
import fsys.stream;
import gdip.bitmap;
import inet.http;

//获取一个网络图片
var pngData = inet.http().get("http://www.baidu.com/img/baidu_logo.gif");

//转换为GDI对象处理
var bitmap = gdip.bitmap( pngData );

//转换为文件流
var stream = fsys.stream();
bitmap.saveToStream(stream,"*.png");

//获取图片字符串 保存到本地
var str  = stream.readAll();
string.save("/test.png",str );

process.explore_select("/test.png");


转个群里讨论的网络小票打印机代码:

import wsock.tcp.client;
var tcpClient = wsock.tcp.client();
var rtn = tcpClient.connect("192.168.1.50",9100);

var rtn = tcpClient.write("1008610086");
tcpClient.write('\n');//打印换行

var rtn = tcpClient.write("123456789");
tcpClient.write('\n');

var str = stirng.fromto("aardio很不错,果然可以打印中文了,厉害了我的哥。");
var rtn = tcpClient.write(str);//不转换的话中文就会乱码
tcpClient.write('\n');

tcpClient.close();

blob.png

tcpClient.writeBuffer(raw.buffer({byte b[3]={0x1B;0x61;0xF}}))

buffer就是缓冲区是一段内存数据

你都写到buffer里发出去就行了

raw.buffer()就是干这个的

原型如下的数据:

blob.png

应该定义为这个

(raw.buffer({byte b[3]={0x1B;0x61;0xF}}))

他定义那些都是转义字符的asc码

定义不定义没关系直接写就行,定义了是为了方便理解

esc键的ascii码十进制表示为27,二进制表示为0001 1011,十六进制表示为0x1B

你发的那个只不过定义了一个变量名字是esc内容是十进制27也就是十六进制1B

免得看到27或者1B不理解什么意思

那么,上面的网络小票打印机可以继续改为:

import wsock.tcp.client;
var tcpClient = wsock.tcp.client();
var rtn = tcpClient.connect("192.168.1.50",9100);
 
var covB = raw.buffer({byte b[3]={0x1B;0x61;0xF}})//加粗代码指令
 tcpClient.writeBuffer(covB,);//加粗
var rtn = tcpClient.write("1008610086");
tcpClient.write('\n');//打印换行
 
var rtn = tcpClient.write("123456789");
tcpClient.write('\n');
 
var str = stirng.fromto("aardio很不错,果然可以打印中文了,厉害了我的哥。");
var rtn = tcpClient.write(str);//不转换的话中文就会乱码
tcpClient.write('\n');
 
tcpClient.close();

这样打印的1008610086就是加粗后的。

blob.png

其他的功能类似操作。

扫描并得到图片中交叉网点坐标:

import win.ui;
/*DSG{{*/
var winform = win.form(text="定位演示";right=850;bottom=644;parent=...)
winform.add(
button={cls="button";text="定位";left=236;top=602;right=607;bottom=636;db=1;z=1};
picGray={cls="plus";left=12;top=22;right=840;bottom=578;aw=1;bgcolor=0;db=1;dr=1;dt=1;edge=1;repeat="scale";z=2}
)
/*}}*/

var calGray = function(num){   
    var b,g,r = gdi.getRgb(num);
    return (77 * r + 151 * g + 28 * b) >> 8;  
}

import console;
import gdip;
import inet.http;
winform.button.oncommand = function(id,event){  

    var bmp = gdip.bitmap("/MsIPaH.png" ,"*.png");  
    var bmpdata = bmp.lockData32();
    
    tab_v = {};
    tab_h = {};
    
    var bits = bmpdata.bits;
    for(h=1;bmp.height){
            var row = bits.rows[h];
        for(w=1;bmp.width){  
                var gray = calGray(row.pixels[w]); 
                if(gray<120 and (h==5 or h==30)){
                            tab_v[w]=1;
                    }
                if(gray<120 and (w==10 or w=50)){
                            tab_h[h]=1;
                    }                
        }
    }
    
    for(h=1;bmp.height){
            var row = bits.rows[h];
        for(w=1;bmp.width){  
                if(tab_v[w] or tab_h[h]){
                            row.pixels[w] = 0xffffffff;
                    }
        }
    }

        for(m,n in tab_v){
                for(k,v in tab_h){
                        console.log("交叉点:",m,k);
                }        
        }
    
    bmp.unlockData(bmpdata); 
    
    winform.picGray.setBackground( bmp )
}

winform.show() 
win.loopMessage();

blob.png

正如图片中那根我自己画的斜线,就找不到了。。。

转自:http://bbs.aardio.com/forum.php?mod=viewthread&tid=13407&extra=page%3D1

旋转和缩放画布示例:利用mouse.hook

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=600)
winform.add(
button={cls="button";text="旋转图片";left=597;top=276;right=714;bottom=370;z=2};
button6={cls="button";text="改变图片大小";left=602;top=126;right=713;bottom=207;z=3};
custom={cls="custom";text="custom";left=0;top=0;right=300;bottom=300;bgcolor=12632256;z=1}
)
/*}}*/

import mouse.hook


//io.open();
/*
import console;
*/

var show = false;

var rotateOn = false; 
var resizeOn = false;

var cusRect = null;         //custom控件的Rect
var angle = 0;                        //鼠标绕图片中心旋转的角度
var mouseSpeed = 10; 
var distance = 0;                //鼠标位置与图片左上角的距离  


var brush = gdip.solidBrush( 0xFFFFFFFF );
var bmp = gdip.bitmap("\37.jpg")
var img = gdip.bitmap(bmp.width,bmp.height)
var graphics = gdip.graphics(img);

//为了模拟绕中心旋转,取得画布平移的XY
//思路:知道两点坐标,可获取中点坐标
var getOffsetXY = function( w,h,angle ){
        
        var sinA = math.sin(math.rad(angle));
        var cosA = math.cos(math.rad(angle));
        
        var x =  (w*cosA-h*sinA)/2 ;
        var y =  (w*sinA+h*cosA)/2 ;
        
        x = w/2 - x;
        y = h/2 - y;
        
        return x,y; 
}

//一定程度避免重复计算
//顺时针旋转1°画布平移的x,y值
var tsltX,tsltY = getOffsetXY( bmp.width,bmp.height,1 );
//逆时针旋转1°画布平移的x,y值
var negTsltX,negTsltY = getOffsetXY( bmp.width,bmp.height,-1 );


//鼠标绕图片中心旋转时相比上一次移动的角度
//很大程度是旋转1°
var offsetAngle = function(cusRect,mx,my){

        var x = mx - (cusRect.right+cusRect.left)/2;
        var y = my - (cusRect.bottom+cusRect.top)/2;
        var newAngle = ..math.round( ..math.deg(..math.atan2(y,x)))
        var offsetAngle = newAngle - angle;        
        angle = newAngle;
                
        return offsetAngle; 
}

//绘制图片
var draw = function( msg,p ){
        show = true;
        gdi.windowBuffer( winform.custom.hwnd,
            function( hdc,hMemDc,hMemBitmap,width,height ){
                    
                    var g = gdip.graphics(hMemDc)
                    g.compositingQuality = 2/*_GdipCompositingQualityHighQuality*/ ;
                g.smoothingMode = 2/*_GdipSmoothingModeHighQuality*/ ;
                    select( msg ) {
                            case "rotate" {
                                    
                                    graphics.fillRectangle(brush,0,0,bmp.width,bmp.height)
                                        graphics.rotate( p.angle, 1/*_MatrixOrderAppend*/ )
                                        graphics.translate( p.tsltX,p.tsltY, 1/*_MatrixOrderAppend*/)
                                        
                                        graphics.drawImageRect(bmp,0,0,bmp.width,bmp.height)
                                        
                                        g.setClipRect(0,0,width,height);
                                        g.drawImageRect(img,0,0,width,height)
                                    
                            }
                            case "room" {
                                    graphics.drawImageRect(bmp,0,0,bmp.width,bmp.height)
                                    //graphics.drawImageRectRect(bmp,0,0,width,height,0,0,bmp.width,bmp.height)
                                        g.drawImageRect(img,0,0,width,height)
                                        //g.drawImageScale(img,winform.custom.getRect())
                                        //io.print(bmp.width,bmp.height,img.width,img.height)
                            }
                            case "redraw" {
                                            
                                        g.drawImageRect(img,0,0,width,height)
                            }
                    }
                        g.delete();
                ::BitBlt(hdc, 0, 0, width, height, hMemDc, 0, 0, 0xCC0020/*_SRCCOPY*/);
            }
        )
}

//定义获取鼠标的移动速度
SystemParametersInfo = ::User32.api("SystemParametersInfoA","int(int uAction,int uParam,int &lpvParam,int fuWinIni)" )

winform.button.oncommand = function(id,event){

        cusRect = winform.custom.getRect(true);
        
        rotateOn = true;
        
        //获得当前鼠标速度以便恢复
        var rs,lpvParam = SystemParametersInfo(0x70/*_SPI_GETMOUSESPEED*/,0,0,0)
        mouseSpeed = lpvParam;
        
        var lowMouseSpeed = 5;
        //降低鼠标速度
        ::User32.SystemParametersInfo(0x71/*_SPI_SETMOUSESPEED*/,0,lowMouseSpeed,0)
        
        var mx,my = win.getMessagePos();

        var x = mx - (cusRect.right+cusRect.left)/2;
        var y = my - (cusRect.bottom+cusRect.top)/2;
        angle = ..math.round( ..math.deg(..math.atan2(y,x)))
        
        var hk = mouse.hook();
        hk.proc = function(msg,x,y,mouseData,injected,flags,timeStamp,extraInfo){
                if( injected ) return;         
            select(msg) {
                    case 0x201/*_WM_LBUTTONDOWN*/{
                        rotateOn = false;
                        hk.close();
                        ::User32.SystemParametersInfo(0x71/*_SPI_SETMOUSESPEED*/,0,mouseSpeed,0);
                        
                        return true; 
                    }
                    case 0x200/*_WM_MOUSEMOVE*/{
                            if(rotateOn){
                                        var offsetAngle = offsetAngle(cusRect,x,y);
                                        
                                        var prama = {
                                                ["angle"] = offsetAngle;
                                        };
                                        select( offsetAngle ) {
                                                case 1 {
                                                        prama = {
                                                                ["angle"] = 1;
                                                                ["tsltX"] = tsltX;
                                                                ["tsltY"] = tsltY;
                                                        }        
                                                        draw( "rotate",prama );
                                                }
                                                case -1 {
                                                        prama = {
                                                                ["angle"] = -1;
                                                                ["tsltX"] = negTsltX;
                                                                ["tsltY"] = negTsltY;
                                                        }
                                                        draw( "rotate",prama );
                                                }
                                                case !0 {
                                                        prama.tsltX,prama.tsltY = getOffsetXY( bmp.width,bmp.height,offsetAngle );
                                                        draw( "rotate",prama );
                                                }
                                        }
                                        
                                }
                    }  
            }   
        }
}



winform.button6.oncommand = function(id,event){

        var mx,my = win.getMessagePos();

        cusRect = winform.custom.getRect(true);
        distance = math.round( math.sqrt( (cusRect.left-mx)**2+(cusRect.top-my)**2 ) );

        resizeOn = true;
        var hk = mouse.hook();
        hk.proc = function(msg,x,y,mouseData,injected,flags,timeStamp,extraInfo){
                if( injected ) return;         
            select(msg) {
                    case 0x201/*_WM_LBUTTONDOWN*/{
                        resizeOn = false;
                        hk.close();

                        return true; 
                    }
                    case 0x200/*_WM_MOUSEMOVE*/{
                            if(resizeOn){
                                        var d = math.round( math.sqrt( (x-cusRect.left)**2+(y-cusRect.top)**2 ) );
                                        
                                        var ratio = math.round( d/distance,2 );
                                        
                                        var        w = (cusRect.right - cusRect.left)*ratio;
                                        var        h = (cusRect.bottom - cusRect.top)*ratio;
                                        
                                        winform.custom.setPos(,,w,h);  //这里窗口会闪烁
                                        draw( "room" );
                                }
                    }  
            }   
        }
        
}




winform.custom.onEraseBkgnd  = function(hwnd,message,wParam,lParam){
        if(show){
                draw( "redraw" );
            return false;
        }
        //show = true;
}




winform.onClose = function(hwnd,message,wParam,lParam){
    bmp.dispose();
        img.dispose();
        graphics.delete();
}

winform.custom.image = "\37.jpg";


winform.show() 
win.loopMessage();

blob.png

转自:http://bbs.aardio.com/forum.php?mod=viewthread&tid=7774&extra=page%3D1

定义画笔:在plus控件上画折线,移动跟随鼠标

这里注意界面中局部变量的用法:


import win.ui;
/*DSG{{*/
winform = win.form(text="绘图演示";right=599;bottom=399;bgcolor=16777215)
winform.add(
plus={cls="plus";left=8;top=9;right=590;bottom=393;notify=1;z=1}
)
/*}}*/

import gdip.pen; 
winform.plus.points ={}
winform.plus.onDrawContent = function(graphics,rc){
    var pen = winform.plus.pen;
    if(pen){
        
        if( #winform.plus.points >=2 ) {
            var pt,pt2;
            for(i=1;#winform.plus.points-1;1){
                var pt,pt2 = winform.plus.points[i],winform.plus.points[i+1] 
                 graphics.drawLine(pen,pt.x,pt.y,pt2.x,pt2.y)
            }
        }
        
        var pt = winform.plus.points[#winform.plus.points]
        if( pt && winform.plus.x2 && winform.plus.y2 ){
            graphics.drawLine(pen,pt.x,pt.y,winform.plus.x2,winform.plus.y2 )
        }
    }
}

winform.plus.onMouseClick = function(wParam,lParam){
    if( !winform.plus.pen )//画笔是否定义
        winform.plus.pen = gdip.pen(0xFFFFFF00,2);//定义画笔
        
    var x,y  = win.getMessagePos(lParam);
    table.push(winform.plus.points,{x=x;y=y} );//把绘制的直线端点都放入数据表中,供重绘用
    winform.plus.redrawTransparent()
}

winform.plus.onMouseMove = function(wParam,lParam){
    winform.plus.x2,winform.plus.y2 = win.getMessagePos(lParam); 
    winform.plus.redrawTransparent();//刷新重绘 
    //winform.plus.redraw()//不刷新,直接绘
}

winform.show()
win.loopMessage();

blob.png

(转)

新手教程:写一个资源管理器

添加的代码如下:

import win.ui.explorer;
var explorer = win.ui.explorer( winform.treeview );
explorer.loadFile(
"~/")


winform.treeview 是树形视图控件,explorer 则是对树形视图的进行包装增加功能的一个新对象( aardio中类似这种用法很多,动态语言擅于实践一个设计原则:多用组合少用继承会写出更简洁的代码 )

explorer.loadFile() 函数用来加载硬盘上的目录,如果不指定任何参数就会打开“我的电脑”列出所有驱动器根目录,这个函数还可以指定模式匹配、或者后缀名通配符等等以显示指定类型的文件,例如 

explorer.loadFile("~/",{ "*.aardio""*.html"})

指定后缀名通配符的参数可以如上是一个数组(以指定多个后缀名),也可以仅仅用一个字符串指定后缀名。注意通配符仅用于限定文件而不会限制目录,无论如何所有子目录总会显示出来。


大家可能注意到了一件事,我在写函数名的时候,哪怕就是在文档里总会在函数后面加上括号,例如 explorer.loadFile(),这是一个原则,aardio函数在任何时候不可以省略后面的括号。现代的编程语言已经被各种语法糖玩坏了,例如函数后面不用写括号,的确这看起来似乎很酷:

withtest {
    ...
}

这种令人迷惑的语法其实就是一个简单的函数调用,或者有不少语言可以省略function关键字,或者用更短的func或者某个标点符号来代替,甚至允许你省略不用写 return, 所以我们现在看到这些时尚拉风的代码迷惑不止时 - 其实他也是一个简单的函数调用。添加这些语法糖非常的容易,我也曾经被诱惑过,但aardio坚持了最简单的语法,定义函数你就必须写 function ,调用函数你就必须写括号,没有一大堆的时尚花式写法以及花式语法糖,实用和简单才是aardio所坚持的原则。


回到正题,explorer对象提供一些事件用于响应用户的操作,示例代码如下:

import win.ui.explorer;
var explorer = win.ui.explorer( winform.treeview );
explorer.loadFile(
"~/")

//用户用鼠标单节点
explorer.onClick = function(filePath,hItem ){
    
}

//用户用鼠标双击节点
explorer.onDoubleClick = function(filePath,hItem ){
    winform.text = filePath
}

//用户鼠标右键点击节点
explorer.onRightClick = function(filePath,hItem,x,y){
        
}

所有回调参数中filePath参数是一个字符串 - 也是用户当前点击的节点所对应的文件路径,而 hItem 是treeview控件的节点句柄(可用于treeview操作节点的函数作为参数 )


如果我们希望用户右键点击节点时弹出右键菜单,可以这样写

//用户鼠标右键点击节点
import win.ui.menu;
explorer.onRightClick = 
function(filePath,hItem,x,y){
    
var hItem,tvht = winform.treeview.hitTest(x,y,true);
    
var menu = win.ui.popmenu(winform)
    menu.add(
"浏览...",
        
function(){
            process.explore_select(filePath)
        }
    )
    menu.popup(x,y,
true);   
}


你也许希望再在我们的资源管理器上添加一个列表视图,当然你可以用listview,一个更简单的方法是使用web.form浏览器控件,浏览器控件可以直接显示文件列表 - 可以省掉很多代码,要创建浏览器控件我们首先要添加一个static控件(或者custom控件也可以 )

增加的代码如下:

import web.form;
var wb = web.form( winform.static );

web.form实际上是IE内核的浏览器组件,上面的wb变量是在static静态控件上进行包装并增加浏览器功能的浏览器对象,我们最常用的一个函数是 wb.go() ,例如打开一个网址就写 wb.go("http://www.aardio.com"),这个函数的参数也可以是一个硬盘目录的路径 - 这时候会显示文件列表视图(就像资源管理器那样)。


我们也可以使用 wb.goDirectory() 函数打开目录,这个函数仍然是调用 wb.go() 函数,但是他会自动获取ShellFolderView对象,并且为浏览器组件添加一个事件 wb.shellFolderSelectionChanged() ,在这个事件里我们可以知道用户点击了哪个具体的文件,也许我们可以添加一个文本框来显示用户点选的文件路径:

上面我们用了一个 if 语句调用  fsys.isDir( filePath ) 判断参数中指定的文件路径是否一个目录,如果是目录我们用 wb.goDirectory( filePath ) 打开并显示文件列表。 

import win.ui;
/*DSG{{*/
var winform = win.form(text="仿资源管理器树形目录";right=719;bottom=414)
winform.add(
edit2={cls="edit";text="edit2";left=31;top=380;right=707;bottom=404;edge=1;z=3};
static={cls="static";text="static";left=253;top=20;right=695;bottom=363;transparent=1;z=2};
treeview={cls="treeview";left=27;top=15;right=236;bottom=369;asel=false;bgcolor=16777215;edge=1;z=1}
)
/*}}*/

import win.ui.explorer;
var explorer = win.ui.explorer( winform.treeview );
explorer.loadFile("~/")

import web.form;
var wb = web.form( winform.static );

//用户点选了列表视图中的文件
wb.shellFolderSelectionChanged = function(filePath) { 
    winform.edit2.text = filePath;
}

//用户用鼠标单节点
explorer.onClick = function(filePath,hItem ){
    if( fsys.isDir( filePath ) ){
        wb.goDirectory( filePath );
    }
    else {
        winform.edit2.text = io.fullpath(filePath); 
    }
}

//用户鼠标右键点击节点
import process;
import win.ui.menu;
explorer.onRightClick = function(filePath,hItem,x,y){
    var hItem,tvht = winform.treeview.hitTest(x,y,true);
    var menu = win.ui.popmenu(winform)
    menu.add("浏览...",
        function(){
            process.explore_select(filePath)
        }
    )
    menu.popup(x,y,true);   
}

winform.show() 
win.loopMessage();

blob.png

转自:https://mp.weixin.qq.com/s/2js9lqhnRQyN5_pie9W4bQ 感谢一鹤老大

界面tab切换效果:

import win.ui;
/*DSG{{*/
mainForm = win.form(text="aardio form";right=759;bottom=469)
mainForm.add(
button={cls="button";text="切换";left=161;top=418;right=516;bottom=458;z=1};
custom={cls="custom";text="custom";left=7;top=9;right=746;bottom=394;clipch=1;z=2};
custom2={cls="custom";text="custom2";left=7;top=9;right=746;bottom=394;z=3}
)
/*}}*/

mainForm.threadCallable();

import win.animate;

mainForm.custom2.show(false);


var frmChild,wb = mainForm.custom.loadForm("\res\tan1.aardio");
//frmChild.show();
import console;
console.open()
var num = 1;
mainForm.button.oncommand = function(id,event){

mainForm.custom.show(false);
var frmChild2,wb2 = mainForm.custom2.loadForm("\res\tan2.aardio");
win.animate.slide(mainForm.custom2.hwnd).show(500,0x2/*水平自右向左*/);

}


mainForm.enableDpiScaling();
mainForm.show();

return win.loopMessage();

新建了两个tan1和tan2的界面,软件中要实现点击按键tan1滑动切换到tan2,但是效果不理想,有待进一步解决

GIF.gif


(转记)

plus控件新增自定义动画功能

最新版已调整FontAwesome字体编码与官方完全一致,plus等控件在使用FontAwesome图标字体时不会与其他非图标文本冲突,因为这个改进,我们可以愉快的混合图标和文字,并且得已支持下面演示的:动画图标功能。


plus控件新增了自定义动画函数startAnimation(),这个函数可以直接指定一个用于旋转显示的FontAwesome图标,仅用一句代码就可以切换到动画图标状态,效果图如下:

import win.ui;
import gdip.fontAwesome;
/*DSG{{*/
var winform = win.form(text="FontAwesome图标字体 - 旋转动画";right=455;bottom=286)
winform.add(
plus={cls="plus";text='\uF25A 开始';left=31;top=214;right=264;bottom=243;color=32768;font=LOGFONT(name='FontAwesome';h=-19);notify=1;z=1}
)
/*}}*/

var hyperlink = {
     color = { 
        hover = 0xFFFF0000;
        active = 0xFF00FF00;
    }
}
winform.plus.skin(hyperlink)


winform.plus.oncommand = function(id,event){

    //按钮以旋转动画显示FontAwesome文字图标
    winform.plus.startAnimation(10,'\uF110'/*_FA_SPINNER*/,"稍候")
    
    winform.setTimeout(function(){
        winform.plus.stopAnimation();//停止动画
    },2000);    
}

winform.show() 
win.loopMessage();

再看一个例子:



附源代码:

import win.ui;
/*DSG{{*/
var winform = win.form(text="自定义动画演示";right=455;bottom=286)
winform.add(
plus={cls="plus";left=21;top=31;right=293;bottom=239;z=1};
)
/*}}*/

var rotationAngle=0
winform.plus.onDrawContent = function(graphics,rc){
     
    graphics.translate( rc.width()/2, rc.height()/2);
    rotationAngle+=5;
    graphics.rotate(rotationAngle);
 
    var brush = gdip.solidBrush(0xFF00FFFF);
    var brush2 = gdip.solidBrush(0xFF0000FF);
    graphics.fillPie(brush, -100, -100, 200, 200, 90, 180);
    graphics.fillPie(brush2, -100, -100, 200, 200, 90, -180);
    graphics.fillPie(brush, -51, 0, 100, 100, 90, -180);
    graphics.fillPie(brush2, -49, -100, 100, 100, 90, 180);
    graphics.fillEllipse(brush, -10, -60, 20, 20);
    graphics.fillEllipse(brush2, -10, 40, 20, 20);
        
    brush.delete();
    brush2.delete();
}

winform.plus.startAnimation(10);


winform.show() 
win.loopMessage();

转自:https://mp.weixin.qq.com/s/KN4-kShinDLXYGEMlOWXmg

简单串口程序:

import win;
import console; 
import sio;

var sport = sio.port("COM3");

//设置串口(波特率,数据位,停止位,校验位)
sport.ioctl(9600,8,1);

//接收到字符时响应事件,注意这个回调函数是线程回调函数
sport.termCntIrqThread(1,function(port){
import sio;
var sport = sio.port(port);
io.print("收到HEX",sport.readHex() );
} )

//ASCII写入
//sport.write("test");

//HEX写入
sport.writeHex(" 74 65 73 74");

console.open();
/*发送文件
sport.transmitAscii("/test.txt",
function(length,bufferSize,buffer,totalLength){
io.print( length,totalLength )
})
*/

console.pause();

//关闭串口
sport.close();


上面的串口程序的封装库有点小问题,发送hex格式第一个字符必需是空格,要不然第一个数据会被认定为ascii码来发送,其他的发送没问题。。。

改动地方如下:

writeHex = function(hex){
if(hex[[1]] != " "){//判断第一个字符
hex = ..string.concat(" ",hex);//连接字符
}
var str = ..string.unhex(hex," "); //以空格拆分
var len = ::Pcomm.sio_write(this.portNumber,str,#str)
if( len < 0 ) return null,errorMessage[len];
return len;
};


刚刚看到plus做界面的应用,顺便把上面动画窗体加进去看看效果。

import win.ui;
/*DSG{{*/
var winform = win.form(text="宽版界面演示";right=722;bottom=432;image=$"\res\images\bg.gif";bkBottom=2;bkLeft=83;bkRight=255;bkTop=110;border="none";parent=...)
winform.add(
btnClose={cls="plus";left=689;top=0;right=715;bottom=27;background="\res\images\close-default.png";dr=1;dt=1;notify=1;z=5};
btnMax={cls="plus";left=662;top=0;right=688;bottom=27;background="\res\images\max-default.png";dr=1;dt=1;z=6};
btnMin={cls="plus";left=635;top=0;right=661;bottom=27;background="\res\images\min-default.png";dr=1;dt=1;z=7};
btnNav1={cls="plus";text="测试按钮";left=18;top=7;right=94;bottom=88;background="\res\images\icon_bg.jpg";bgcolor=1949696;bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;color=16777215;dl=1;dt=1;foreground="\res\images\excel.png";notify=1;paddingBottom=7;paddingLeft=5;paddingRight=5;paddingTop=5;valign="bottom";x=0.5;y=0.20000000298023;z=3};
btnNav2={cls="plus";text="测试按钮2";left=115;top=7;right=191;bottom=88;background="\res\images\icon_bg.jpg";bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;color=16777215;dl=1;dt=1;foreground="\res\images\feed.png";notify=1;paddingBottom=7;paddingLeft=5;paddingRight=5;paddingTop=5;valign="bottom";x=0.5;y=0.20000000298023;z=2};
btnNav3={cls="plus";text="测试按钮3";left=212;top=7;right=288;bottom=88;background="\res\images\icon_bg.jpg";bkBottom=3;bkLeft=7;bkRight=8;bkTop=2;clip=1;color=16777215;dl=1;dt=1;foreground="\res\images\rss.png";notify=1;paddingBottom=7;paddingLeft=5;paddingRight=5;paddingTop=5;valign="bottom";x=0.5;y=0.20000000298023;z=1};
custom={cls="custom";left=5;top=96;right=717;bottom=431;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;z=4}
)
/*}}*/

import win.animate;
//最大化按钮样式
winform.btnMax.skin(
checked = { //还原按钮的样式
background = { 
hover = "/res/images/restore-hover.png";
active = "/res/images/restore-active.png";
default = "/res/images/restore-default.png"; 
}
}
//下面是最大化按钮的样式
background = { 
hover = "/res/images/max-hover.png";
active = "/res/images/max-active.png";
default = "/res/images/max-default.png"; 
}
)  

//最小化按钮样式
winform.btnMin.skin( 
background = { 
hover = "/res/images/min-hover.png";
active = "/res/images/min-active.png"; 
default = "/res/images/min-default.png"; 
}
)

//关闭按钮样式
winform.btnClose.skin(
background = { 
hover = "/res/images/close-hover.png";
active = "/res/images/close-active.png";
default = "/res/images/close-default.png"; 
}
)


//最大化按钮
winform.btnMax.oncommand = function(id,event){
//点击最大化或还原按钮,并将当前窗体是否最大化设为控件的checked状态
winform.btnMax.checked = winform.hitmax();
}
 
//最小化按钮
winform.btnMin.oncommand = function(id,event){
winform.hitmin()


//关闭按钮
winform.btnClose.oncommand = function(id,event){
winform.close()

 

//添加下面的代码以支持鼠标拖动窗体
winform.wndproc = {
[ 0x201/*_WM_LBUTTONDOWN*/ ] = function(hwnd,message,wParam,lParam){
winform.hitCaption();
}
[ 0x203/*_WM_LBUTTONDBLCLK*/] = function(hwnd,message,wParam,lParam){
winform.btnMax.checked = winform.hitmax();//双击标题栏最大化
}
}
 
namespace theme{ 
mainButton = {
background = { 
hover = "/res/images/main-nav-bg-hover.png"; 
active = "/res/images/main-nav-bg-hover.png"; 
default = "/res/images/main-nav-bg.png";  
}
checked = { //指定选中状态的样式
background = { 
hover = "/res/images/main-nav-bg-hover.png"; 
active = "/res/images/main-nav-bg-hover.png"; 
default = "/res/images/main-nav-bg-hover.png";  
}
}
group = "main";//这个参数指定按钮是单选按钮分组,使该分组中的按钮同时只能选中一个
}


winform.btnNav3.skin( theme.mainButton ) 
winform.btnNav2.skin( theme.mainButton ) 
winform.btnNav1.skin( theme.mainButton  )

var frmPage1 = winform.custom.loadForm("\forms\page1.aau" );
var frmPage2 = winform.custom.loadForm("\forms\page2.aau"  );
var frmPage3 = winform.custom.loadForm("\forms\page3.aau" );
winform.btnNav1.oncommand = function(id,event){  
winform.custom.showChildren(false);
//frmPage1.show(true); 
win.animate.slide(frmPage1.hwnd).show(500)//,0x2/*水平自右向左*/);  
}
winform.btnNav2.oncommand = function(id,event){ 
winform.custom.showChildren(false);  
//frmPage2.show(true); 
win.animate.slide(frmPage2.hwnd).show(500)//,0x2/*水平自右向左*/);    
}
winform.btnNav3.oncommand = function(id,event){ 
winform.custom.showChildren(false);
//frmPage3.show(true);
win.animate.slide(frmPage3.hwnd).show(500,0x2/*水平自右向左*/);    
}

//添加阴影边框
import win.ui.shadow;
win.ui.shadow( winform,70,3 );

//下面的代码为窗体添加可拖动改变大小的边框
import win.ui.resizeBorder;
win.ui.resizeBorder( winform ); 

//限制最大化时不要覆盖任务栏
import win.ui.minmax;
win.ui.minmax( winform );

winform.show() 
win.loopMessage();

这里关键是动画窗体的使用方法:

先把几个窗体都加载进去,显示的话显示最后一个加载的,然后再每次准备点击大图标的地方先取消所有子窗体的显示,然后在显示特定的,因为用动画窗体,所以直接用加载的frmpage的句柄。

winform.btnNav3.oncommand = function(id,event){ 
winform.custom.showChildren(false);
//frmPage3.show(true);
win.animate.slide(frmPage3.hwnd).show(500,0x2/*水平自右向左*/);    
}

GIF.gif

利用C语言编译器生成dll供其他软件调用:

示例:有一个东西需要由输入的数值来计算出相应的位移变化量, 思路是:生成两个函数调用,一个init初始化参数,一个calc计算输出.

//生成DLL 

code = /** 
#include <stdio.h>
#include <math.h>

//默认值
double dataR = 0.0;
double dataX1 = 0.0;
double dataX2 = 0.0;
double dataY = 0.0;

__declspec(dllexport) void uVwInit( double dR,double dx1,double dx2,double dy ) 
{     
dataR = dR;
dataX1 = dx1;
dataX2 = dx2;
dataY = dy;


__declspec(dllexport) void uVwCalc( double angle,double* dx1,double* dx2,double* dy ) 
{     
*dx1 = dataR * cos(( angle + dataX1 ) * 3.1415926 / 180 ) - dataR * cos( dataX1 * 3.1415926 / 180 );
*dx2 = dataR * cos(( angle + dataX2 ) * 3.1415926 / 180 ) - dataR * cos( dataX2 * 3.1415926 / 180 );
*dy = dataR * sin(( angle + dataY ) * 3.1415926 / 180 ) - dataR * sin( dataY * 3.1415926 / 180 );
}  
**/
 
import tcc; 
vm = tcc( );//创建编译器 
vm.addLib( 
"user32",
"kernel32",
"gdi32"

vm.output( "/uVwCalc.dll", code ) //编译C源码,生成DLL
vm.close(); //收工

import console;
console.open()
//加载生成的DLL
var dll = raw.loadDll( "/uVwCalc.dll",,"cdecl");

//导入API,记住第二个参数需要指定cdecl调用约定(也就是C语言调用约定)
uVwInit = dll.api( "uVwInit","void(double dataR,double dataX1,double dataX2,double dataY)" );
uVwCalc = dll.api( "uVwCalc","void(double angle,double& dx1,double& dx2,double& dy)" ); 

uVwInit(53.74,45,315,225);//调用初始化

 var stx1,stx2,sty ;
 var s1,s2,s3 = uVwCalc(1,0,0,0);
 console.log( s1,s2,s3 );
 var s1,s2,s3 = uVwCalc(2,0,0,0);
 console.log( s1,s2,s3 );
 
console.pause();

生成了dll之后如果要给labview调用,最好是写一个h头文件.格式如下:

/*
---------------------------------------------------------------
文件名称:uVwCalc.h
---------------------------------------------------------------
*/
#ifdef UVWCALC_EXPORTS
#define UVWCALC_API __declspec(dllexport)
#else
#define UVWCALC_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************
*函数名称:uVwInit
*输    入:dR  通过连接在个周四的交叉滚柱轴承中心的假设圆半径(mm)
          dx1 连接在X1轴上的交叉滚柱轴承中心的角度位置(mm)
  dx2 连接在X2轴上的交叉滚柱轴承中心的角度位置(mm)
  dy  连接在Y轴上的交叉滚柱轴承中心的角度位置(mm)
*输    出:空
*功    能:初始化UVW位置参数
*示    例:初始化为120平台参数
void  uVwInit( 53.74 , 45 , 315 , 225 );
******************************************************/
UVWCALC_API
extern void  uVwInit (double dR,double dx1,double dx2,double dy);
/*****************************************************
*函数名称:uVwCalc
*输    入:angle 移动角度
*输    出:dx1 X1轴的相对进给量(mm)
  dx2 X2轴的相对进给量(mm)
  dy Y轴的相对进给量(mm)
*功    能:计算UVW平台各轴进给量
*示    例:移动3.2度
double* dx1;
double* dx2;
double* dy;
void  uVwCalc(3.2,dx1,dx2,dy);
******************************************************/
UVWCALC_API
extern void uVwCalc( double angle,double* dx1,double* dx2,double* dy );

#ifdef __cplusplus
}
#endif

blob.png

soImage库怎么输出加载并加工之后的图片到窗口?

下面是利用这个库,把一张彩色图片转换灰度之后输出的窗口.

import soImage;

var img = soImage();
img.load("\res\27.bmp");
//灰度变换
img.grayScale();
mainForm.picGray.background = img.getBytes("*.bmp");//输出图像数据作为plus的背景,这里的bmp格式可以更换..

blob.png

OCR识别Bmp图片内文本

import win.clip;
import win.util.tray;
import win.ui;
/*DSG{{*/
var winform = win.form(parent=...; text="OCR识别Bmp";acceptfiles=1;bottom=327;right=419 )
winform.add( 
static={ right=59;bottom=27;text="文件名";left=16;top=12;font=LOGFONT( name="宋体";h=-12 );z=1;transparent=1;cls="static" };
static2={ bottom=311;text="";left=16;top=43;font=LOGFONT( name="宋体";h=-12 );notify=1;z=3;transparent=1;right=402;edge=1;cls="static" };
edit={ bottom=29;right=402;left=68;top=10;font=LOGFONT( name="宋体";h=-12 );z=2;text="请拖入需要识别的Bmp图片";edge=1;cls="edit" }
)
/*}}*/

winform.static2.oncommand = function(id,event){
 winform.static2.text=""
}

识别=function(...){
 import com;
 import win;
 //创建MODI对象(必须安装office2003中的Microsoft Document Imaging组件)
 mdoc = com.CreateObject('MODI.Document');
 if(not mdoc){
     win.msgbox('请将安装office2003及Microsoft Document Imaging组件','屏幕ocr文字识别')
     return false;
 };
 
 //导入图片
 //mdoc.Create( io.fullpath("\test.bmp") );
 mdoc.Create( filename );
 //进行OCR识别,参数分别为语言ID,是否自动旋转,是否自动拉伸
 mdoc.OCR( 0x804,0,0);
 
 var mi = mdoc.Images(0);
 //快速获取取全部文本
 //win.msgbox(mi.Layout.Text,'mdoc.Images(0).Layout.Text');
 winform.static2.text=mi.Layout.Text
 win.clip.write("")
 win.delay(5)
 win.clip.write(winform.static2.text)
}

/*拖动消息处理{{*/
winform.wndproc = function(hwnd,message,wparam,lparam){
 select(message) {//判断消息类型
  
  case 0x233/*_WM_DROPFILES*/  //拖动消息
  { 
   filename=win.getDropFile(wparam )[1] //取得文件名
   //winform.txtEdit.text = filename; //edit控件显示文件名
   //winform.redraw() 
   win.util.tray.pop(filename,"文件名")
   winform.edit.text=filename;
   识别()
  } 
 }
}//endpro
/*}}*/

/*
mdoc.OCR 函数的第一个参数指定语言ID
在简体中文office中可选的语言ID有:
自动选择 0x800
英语 9
简体中文 0x804
*/ 

winform.show() 
win.loopMessage();
win.clip.write("")
return winform;


【Wiz】【com】提取库文件智能提示,添加至Wiz

//提取库文件智能提示,添加至Wiz
//提取智能提示代码参考“http://bbs.aardio.com/thread-4746-1-1.html”
import win.ui;
import fsys.file;
import fsys;
import console;
import com;
import process;

//创建WizDatabase对象
wizDb = com.CreateObject("WizKMCore.WizDatabase")
wizDb.open()//打开默认数据库
aardioLibFolder=wizDb.GetFolderByLocation("/lib",1)//获取根文件夹/lib,不存在则自动创建
//console.log(aardioFolder.name)

addWizdoc=function( wizPath,fullPath){
    //console.log("参数",wizPath,fullPath)
    var tpath=io.splitpath(fullPath)
    var startInd=string.find(tpath.dir,"\\lib" )
    var wizdir=string.sub(tpath.dir,startInd,#tpath.dir-1)
    //console.log("wizdir: ",wizdir)
    var myFolder=wizDb.GetFolderByLocation(wizdir,1)//子文件夹不存在则自动创建
    //console.log(myFolder.name)
    //添加笔记
    var  wizDoc = myFolder.CreateDocument(tpath.name,tpath.name,io.fullpath(wizPath) );
    wizDoc.UpdateDocument(io.fullpath(wizPath), 0); 
    win.delay(1000)
}

libToTxt = function(){
    fsys.createDir("\zdy")
    fsys.enum( io._exedir + "\lib", 
                "*.aau", 
                function(dir,file,fullpath,findData){ 
                    var ldir=""
                    if(file){ 
                        //拆分文件路径为多个部份,并返回一个table对象tpath
                        tpath=io.splitpath(fullpath)
                        //路径开始位置
                        var wz=string.find(tpath.dir,"lib" );
                        if(wz!=null){
                            //截取路径
                            ldir=string.sub(tpath.dir,wz,#tpath.dir)
                            if(!io.exist("\zdy\"+ldir)){
                                //创建文件夹路径
                                fsys.createDir("\zdy\"+ldir)
                                console.log("创建目录:"+ldir)  
                            }
                            //打开文件
                            fsysfile=fsys.file(fullpath)
                            var lsstr ="" ;
                            //读入文件到变量
                            lsstr= fsysfile.read(-1)
                            var str=""
                            //搜索内容关键字位置,用于截取内容
                            for ia,j in string.gSearch(lsstr,"intellisense"){
                                //格式化连接字符串用于分割
                                str=str++ia++"-"++j++"-"
                            }
                            var t={}
                            //分割字符串
                            t=string.split(str,"-")
                            //获得数组最大数
                            tt=table.count(t)-1
                            var zzstr ="" ;
                            for(ib=1;tt;4){
                                //截取字符串内容,并组合
                                zzstr=zzstr++string.sub(lsstr,t[ib],t[ib+3])++'\r\n\r\n'
                            }
                            //保存为txt文件
                            var wizpath="\zdy\"++ldir+tpath.name++".txt"
                            string.save(wizpath,zzstr )
                            //行尾添加html换行符
                            var str=""
                            for line in io.lines(io.fullpath(wizpath)) { 
                                str=str+line+"<br>"
                            }
                            string.save(wizpath,str )
                            win.delay(200)
                            console.log(wizpath)
                            //添加到Wiz
                            addWizdoc(wizpath,fullpath)
                        }
                    };
                } 
            );
    //wizDb.EmptyDeletedItems()//清空Wiz[已删除]文件夹
    wizDb.Close();//关闭数据库
    execute("pause")
    io.close()
}

libToTxt()

转自:http://bbs.aardio.com/home.php?mod=space&uid=27&do=blog&id=1287

htmlayout界面中定位并显示winform控件:

var t_log = wbLayout.getEle("t_log");
var x,y,w,h = t_log.getPos();
console.log(x,y,w,h);
mainform.button.setPos(x,y);

QQ图片20171009222543.gif


这样的功能是为了能够使用winform里面控件的其他功能,比如:视频,摄像头,等等

运行时如何用鼠标拖动控件的位置与大小

import win.ui;
/*DSG{{*/
var winform = ..win.form( bottom=399;parent=...;right=599;text="拖动控件" )
winform.add( 
button={ bottom=275;text="button";left=221;top=228;z=1;right=312;cls="button" }
)
/*}}*/

import mouse;

var moveFlag,bx,by;

winform.button.wndproc = function(hwnd,message,wParam,lParam){
        select( message ) { 
                case 0x201/*_WM_LBUTTONDOWN*/{
                        moveFlag = true;
                        var x,y = mouse.getPos();
                        bx,by = win.toClient(winform.button.hwnd,x,y);
                }
                case 0x202/*_WM_LBUTTONUP*/ {
                        moveFlag = false;
                }
                case 0x200/*_WM_MOUSEMOVE*/{
                        var x,y = mouse.getPos();
                        
                        var fx,fy = win.toClient(winform.hwnd,x,y)
                        if(moveFlag){
                                winform.button.setPos(fx-bx,fy-by)
                        }
                }
        }
}

winform.show() 
win.loopMessage();


1个窗口拖动,另外1个跟随一起动的效果


import win.ui; 
/*DSG{{*/
mainForm = ..win.form( text="主窗口 - 拖动他试试";right=542;bottom=229 )
mainForm.add(
    static={cls="static";text="1";left=248;top=86;right=286;bottom=139;z=1}
)
/*}}*/

var 子窗口 = /***
var frmOther = ..win.form(cls="my_favorites";text="子窗口";right=657;bottom=118;parent=...)
frmOther.add(
    static={cls="static";text="2";left=303;top=44;right=362;bottom=78;transparent=1;z=1}


frmOther.show();
return frmOther;
***/
var frmOther = mainForm.loadForm( 子窗口 /* "/dlg/frmOther.aardio" */ );

mainForm.show() 
mainForm.xSave,mainForm.ySave = mainForm.getPos();

mainForm.wndproc = function(hwnd,message,wParam,lParam ){         
    select(message) { 
       case( 0x3/*_WM_MOVE*/ ){
            var x,y,cx,cy = mainForm.getPos();
            var xOther,yOther,cxOther,cyOther = frmOther.getPos(); 
            frmOther.setPos( xOther+(x-mainForm.xSave),yOther+(y-mainForm.ySave),cxOther,cyOther);
            mainForm.xSave,mainForm.ySave = x,y;
       } 
    }        
}        

win.loopMessage();

GIF.gif

滚动条信息获取和设置

import console;
console.open();
//滚动条信息集
class INFO {
   INT cbSize = 28;
   INT fMask = 23;
   int min;
   int max;
   INT page;
   int pos;
   int trackPos;

var info = INFO();
//获取滚动条信息集合
 ::User32.GetScrollInfo(winform.listview.hwnd,0x1/*_SB_VERT*/,info )
console.dump(info);
//import win.ui.scrollbar;
//var scrollbar = win.ui.scrollbar(winform.listview.hwnd,true);
//scrollbar.ShowScrollBar(false);
//scrollbar.hide = true;
//::User32.ShowScrollBar(winform.listview.hwnd,0x1/*_SB_VERT*/,0)
//利用获取到的信息设置滚动条的最大最小和分页
scrollbar.setRange(1,info.max*60,info.page*60);


class INFO {
   INT cbSize = 28;
   INT fMask = 23;
   int min;
   int max;
   INT page;
   int pos;
   int trackPos;


var info = INFO();

以上代码中的cbsize = 28

为什么呢? 因为这个class里面有7个INT , 一个INT占4个字节,总共28个字节....

fmask这个呢?

这个是滚动条信息类,0x17就是23,意思是所有信息


以上FontAwome字体图标走了个误区...

一心想要用plus进行显示,其实可以listview直接设置为这个字体,显示即可.....

但需要导入fWA字体库;

import win.fontAwesome;


var i,j = 1,1;
winform.listview.addItem();
var tab = {};
for m in string.gmatch(oldcode ,"\[.*?\]") { 
m = string.replace(m,"@[&amp;#x","");
m = string.replace(m,"@;","");
m = string.replace(m,"@[","");
m = string.replace(m,"@]","");
m = string.upper(m);

if(m!=""){
var strtext = "\u" ++ m;
var sss = string.unescape(strtext);
winform.listview.setItemText( sss,i,j);
}
j++;
if(j > 5)
{
j = 1;
i++;
winform.listview.addItem();

}

}

这个字体库有三个:

import gdip.fontAwesome;
import win.fontAwesome;
import web.layout.fontAwesome;

用到的地方不一样,调用就不一样....

继续研究FWA字体图标listview+plus,终于搞定.

利用了listview滚动条pos和客户区重绘事件.

顺便界面里面加了plus的动画演示....

GIF.gif

import win.ui;
import gdip.fontAwesome;
import win.clip;
/*DSG{{*/
var winform = win.form(text="FontAwesome图标字体";right=800;bottom=564;bgcolor=8421376;border="none";composited=1)
winform.add(
listview={cls="listview";left=2;top=42;right=799;bottom=522;bgcolor=16777215;font=LOGFONT(name='FontAwesome';h=-16;weight=700);gridLines=1;msel=false;vscroll=1;z=5};
plus={cls="plus";text='\uF057';left=764;top=6;right=799;bottom=41;color=16777215;font=LOGFONT(name='FontAwesome';h=-29;weight=700);notify=1;z=1};
plus2={cls="plus";text='\uF06C';left=3;top=6;right=38;bottom=41;align="left";color=16777215;font=LOGFONT(name='FontAwesome';h=-29;weight=700);z=2};
plus3={cls="plus";text="FontAwesome图标字体查看器";left=42;top=6;right=366;bottom=41;align="left";color=16777215;font=LOGFONT(name='Segoe UI Symbol';h=-16;weight=700);z=3};
plus4={cls="plus";text='\uF056';left=727;top=6;right=762;bottom=41;color=16777215;font=LOGFONT(name='FontAwesome';h=-29;weight=700);notify=1;z=4};
plus5={cls="plus";text='\uF011动画演示...';left=0;top=527;right=214;bottom=563;color=16777215;font=LOGFONT(name='FontAwesome';h=-29;weight=700);notify=1;z=6};
plus6={cls="plus";text='\uF244';left=748;top=529;right=800;bottom=565;color=16777215;font=LOGFONT(name='FontAwesome';h=-29;weight=700);z=7}
)
/*}}*/

var battle = 244;
tmid = winform.addtimer(
400/*毫秒*/,
function(hwnd,msg,id,tick){//定时执行代码
var batProgress = "\uF" ++ battle;
winform.plus6.text = string.unescape(batProgress);
battle--;
if(battle<240){
battle = 244;
}
//winform.killtimer(id)//移除此定时器
//winform.settimer(id,2000)//重新设定时间间隔
}
);


winform.plus5.skin(
color = {
hover = "0xFFFF0000";
}
)
winform.plus5.oncommand = function(id,event){
winform.close();
}
winform.plus5.startAnimation(10,'\uF011',"动画演示...")
winform.plus4.skin(
color = {
hover = "0xFFFF0000";
}
)
winform.plus4.oncommand = function(id,event){
winform.show(0x6/*_SW_MINIMIZE*/);
}

winform.plus.skin(
color = {
hover = "0xFFFF0000";
}
)

winform.plus.oncommand = function(id,event){
winform.close();
}

winform.wndproc = function(hwnd,message,wParam,lParam){
select( message ) { 
case 0x201/*_WM_LBUTTONDOWN*/{
winform.hitCaption();
}
else{
}
}
//无返回值则继续调用默认回调函数
}


import win.imageList;
var imagelist = win.imageList(1,60);
winform.listview.setImageList(imagelist, 1/*_LVSIL_NORMAL*/);
//移除列标题
winform.listview.modifyStyle(,0x4000/*_LVS_NOCOLUMNHEADER*/)
winform.listview.insertColumn("AA",155);
winform.listview.insertColumn("BB",155);
winform.listview.insertColumn("CC",155);
winform.listview.insertColumn("DD",155);
winform.listview.insertColumn("EE",158);

/*FW网页代码{{*/



 
var oldcode = /*****
   
        <div class="col-md-4 col-sm-6 col-lg-3 col-print-4">
          <small class="text-muted pull-right">4.4</small>
          <i class="fa fa-fw" aria-hidden="true" title="Copy to use 500px">&#xf26e;</i> fa-500px
          <span class="text-muted">[&amp;#xf26e;]</span>
        </div>
        <div class="col-md-4 col-sm-6 col-lg-3 col-print-4">
          <small class="text-muted pull-right">4.7</small>
          <i class="fa fa-fw" aria-hidden="true" title="Copy to use address-book">&#xf2b9;</i> fa-address-book
          <span class="text-muted">[&amp;#xf2b9;]</span>
        </div>
        <div class="col-md-4 col-sm-6 col-lg-3 col-print-4">
          <small class="text-muted pull-right">4.7</small>
          <i class="fa fa-fw" aria-hidden="true" title="Copy to use address-book-o">&#xf2ba;</i> fa-address-book-o
          <span class="text-muted">[&amp;#xf2ba;]</span>
        </div>
        
 *****/
/*}}*/
var i,j = 1,1;
winform.listview.addItem();
var plustab = {};
for m in string.gmatch(oldcode ,"\[.*?\]") { 
//console.dump(m)
//m = string.replace(m,"@&","");
m = string.replace(m,"@[&amp;#x","");
m = string.replace(m,"@;","");
m = string.replace(m,"@[","");
m = string.replace(m,"@]","");
m = string.upper(m);

if(m!=""){
var strtext = "\u" ++ m;
table.push(plustab,strtext);
}

j++;
if(j > 5)
{
j = 1;
i++;
winform.listview.addItem();
}

}

//滚动条信息集
class INFO {
                  INT cbSize = 28;
                  INT fMask = 23;
                  int min;
                  int max;
                  INT page;
                  int pos;
                  int trackPos;
        } 
var info = INFO();
//获取滚动条信息集合
::User32.GetScrollInfo(winform.listview.hwnd,0x1/*_SB_VERT*/,info )
//设置一个滚动条位置变量
winform.listview.vpos = null;
//设置一个存储上次添加过的plus名称表
winform.listview.preplus = {};
winform.listview.onnotify = function(id,code,ptr){ 
if( code == 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ ){ //如果客户区重绘事件
//获取滚动条信息
::User32.GetScrollInfo(winform.listview.hwnd,0x1/*_SB_VERT*/,info )
//如果滚动条位置pos改变,过滤掉点击产生的重绘
if(winform.listview.vpos != info.pos){
winform.listview.vpos = info.pos;
//如果有已经显示过plus
if(#winform.listview.preplus != 0){
for(ii=1;#winform.listview.preplus;1){
//隐藏显示过的plus
winform.listview[winform.listview.preplus[ii]].hide = true;

}
winform.listview.preplus = {}
}
i = 1 + info.pos;//行
j = 1; //列
//更新查找表头
var tabindex = 5*info.pos + 1;
for(hang=1;(info.page+1)*5;1){
//屏蔽尾部可能的空白无数据块
if(tabindex > #plustab){
break;
}
var fwText = string.unescape(plustab[tabindex]);
winform.listview.addCtrl(
["plusA"++ i ++ j] ={ cls="plus";text= fwText;left=10;top=10;right=50;bottom=50;color=8421376;font=LOGFONT(name='FontAwesome';h=-38;weight=700);hide=1;};
)
//将生成的plus名称都添加到表
table.push(winform.listview.preplus,"plusA"++ i ++ j);
var rc=winform.listview.getItemRect(i,j,,2);
winform.listview["plusA"++ i ++ j].setRect(rc);
//设置鼠标经过事件样式
         winform.listview["plusA"++ i ++ j].skin(
color = {
hover = "0xFFFF0000";
}
)
winform.listview["plusA"++ i ++ j].show();
         winform.listview["plusA"++ i ++ j].oncommand = function(id,event){
winform.msgbox(string.escape(fwText) ++ "已复制! " );
win.clip.write(string.escape(fwText));
}
tabindex++;
j++;
//一行五个块结束
if(j > 5)
{ //增加行
j = 1;
i++;
}
}

}

}
}


winform.show() 
win.loopMessage();

终于了却一桩心事....

listbox实现鼠标拖拽排序功能:

实现方法: 鼠标点击listbox的任意一行的时候,利用addctrl()功能,添加一个plus控件,控件text文本内容就取准备拖拽的这个item文本,当松开拖拽的时候,先判断是否拖拽到了其他行,如果是,那么就先删除原先所在行,在插入到现在选定行上部.

GIF.gif

代码如下:

import win.ui;
/*DSG{{*/
var winform = win.form(text="listbox实现鼠标拖拽排序功能";right=408;bottom=362;parent=...)
winform.add(
listbox={cls="listbox";left=15;top=12;right=398;bottom=337;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(name='Verdana');hscroll=1;items={};vscroll=1;z=1}
)
/*}}*/

//设置字体大小来调整listbox每行的高度
winform.listbox.setFont(point=40;name="宋体");

for(i=1;50;1){
winform.listbox.add("abcd"++ i )
}

import mouse;
var mouseLeftdown,mouseDragmove,bx,by;//鼠标左键按下,鼠标拖拽移动
var plusAkeydownPosX,plusAkeydownPosY;//拖动时候鼠标在plus上面的位置
var preItem;//存储拖拽的序号

winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
select( message ) { 
case 0x205/*_WM_RBUTTONUP*/{
var x,y = win.getMessagePos();  
var item = winform.listbox.hitTest(x,y,true); 
if( item ){
winform.listbox.selIndex = item;
winform.popmenu.popup(x,y,true)
}

case 0x201/*_WM_LBUTTONDOWN*/{
//鼠标左键按下了
mouseLeftdown = true;
//记录下此时的xy
plusAkeydownPosX,plusAkeydownPosY = mouse.getPos();

}
case 0x202/*_WM_LBUTTONUP*/
{
//鼠标左键松开了
            mouseLeftdown = false;
            if(mouseDragmove){
             mouseDragmove = false;
winform.listbox.plusA.hide = true;
//获取当前选中项
if(winform.listbox.selIndex != preItem){
winform.listbox.delete(preItem);
winform.listbox.add(winform.listbox.plusA.text,winform.listbox.selIndex);
}

            }
}
case 0x200/*_WM_MOUSEMOVE*/{
if(mouseLeftdown){
if(!mouseDragmove){

//先判断是否在有效行上点击
var item = winform.listbox.hitTest(x,y,true);
if(item){
preItem = item;
//获取点击行的尺寸
var rc = winform.listbox.getItemRect(item);
//给listbox添加一个plus
winform.listbox.addCtrl(
plusA ={ cls="plus";left=0;top=0;right=50;bottom=50;autoResize=false;align="left";hide=1;bgcolor=14466531;edge=1;clip=1;notify=1;z=10; }
)
//设置plus的大小和位置
winform.listbox.plusA.setRect(rc);
//设置plus的字体
winform.listbox.plusA.setFont(winform.listbox.getFont());
//设置plus的文本
winform.listbox.plusA.text = winform.listbox.getItemText(item);
//显示
winform.listbox.plusA.show();
mouseDragmove = true;
//格式化鼠标位置为相对于被点击的按钮的位置坐标
             bx,by = win.toClient(winform.listbox.plusA.hwnd,plusAkeydownPosX,plusAkeydownPosY);
}
}else {
var x,y = mouse.getPos();
//格式化鼠标当前位置为相对于软件窗口位置坐标
             var fx,fy = win.toClient(winform.listbox.hwnd,x,y)
//设置按钮位置为相对于软件窗口的位置
                 winform.listbox.plusA.setPos(fx-bx,fy-by);
                 winform.listbox.plusA.redraw();
}

}
}
}
}

winform.show() 
win.loopMessage();

发现前两天学习的listview+_plus还是意义蛮大的,至少会用这种方式实现好多东西了...O(∩_∩)O~

在listbox基础上稍加改动实现了listview鼠标拖拽排序功能:

方法:

listview+addctrl(plus),做了一个蒙板,通过listview的两个 通知 和 消息回调 拦截鼠标事件完成拖拽定位操作.

GIF.gif

import win.ui;
/*DSG{{*/
var winform = win.form(text="listview拖拽排序功能演示";right=614;bottom=300;parent=...)
winform.add(
listview={cls="listview";left=26;top=23;right=575;bottom=274;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;edge=1;fullRow=1;gridLines=1;msel=false;z=1}
)
/*}}*/

//import console;
//console.open();
//鼠标流程1:按下--拖拽--松开了
//鼠标流程2:按下--单击(按松一次)--移动
import mouse;
var mouseLeftdown,mouseDragmove,bx,by;//鼠标左键按下,鼠标拖拽移动
var plusAkeydownPosX,plusAkeydownPosY;//拖动时候鼠标在plus上面的位置
var preItem,newItem;//存储拖拽的序号


import win.imageList;
var imaglist = win.imageList(1,40);
winform.listview.setImageList( imaglist,2/*_LVSIL_STATE*/ )

winform.listview.insertColumn("测试项1",80) 
winform.listview.insertColumn("测试项2",100) 
winform.listview.insertColumn("测试项4",100)
winform.listview.insertColumn("测试项3",-1) 
for(i=1;33;1){
    winform.listview.addItem({tostring(i);"点我"++tostring(i)++"1";"点我"++tostring(i)++"2";"点我"++tostring(i)++"3"});
}


winform.listview.wndproc = function(hwnd,message,wParam,lParam){
select( message ) { 
case 0x201/*_WM_LBUTTONDOWN*/

//console.log("左键按下")
//鼠标左键按下了
            mouseLeftdown = true;
            //记录下此时的xy
            plusAkeydownPosX,plusAkeydownPosY = mouse.getPos();

}
case 0x202/*_WM_LBUTTONUP*/

//console.log("左键松开了")
mouseLeftdown = false;
if(mouseDragmove){
mouseDragmove = false;
winform.listview.plusA.hide = true;
if(newItem != preItem){
var tabtext = {};
for(i=1;winform.listview.columnCount;1){
table.push(tabtext,winform.listview.getItemText(preItem,i));
}
//注意这里!!!
//会导致一个问题:
//向上拖动后,会在选中行上部添加
//向下拖动后,会在选中后下部添加
//其实仔细想想这样也符合常理....于是不改了...
winform.listview.delItem(preItem);
winform.listview.addItem(tabtext,newItem);

}

}

}
case 0x200/*_WM_MOUSEMOVE*/{
//console.log("鼠标移动111111")
if(mouseDragmove){
var x,y = mouse.getPos();
var fx,fy = win.toClient(winform.listview.hwnd,x,y)
newItem = winform.listview.hitTest();
winform.listview.selIndex = newItem;
winform.listview.plusA.setPos(fx-bx,fy-by);
winform.listview.plusA.redraw();
//winform.listview.redraw();
}

}

}
}
 
winform.listview.onnotify = function(id,code,ptr){
select( code ) { 

case 0xFFFFFFFE/*_NM_CLICK*/ {
//console.log("左键单击(按松一次)")
mouseLeftdown = false;
}
case 0xFFFFFF93/*_LVN_BEGINDRAG*/{
//console.log("拖拽22222")
//先判断是否在有效行上点击
if(mouseLeftdown){
            var item = winform.listview.hitTest(plusAkeydownPosX,plusAkeydownPosY,true);
if(item){
preItem = item;
var rc = winform.listview.getItemRect(item);
winform.listview.addCtrl(
plusA ={ cls="plus";left=0;top=0;right=50;bottom=50;autoResize=false ;bgcolor=12639424;hide=1;edge=1; clip=1;z=10; }

)
winform.listview.plusA.setRect(rc);
winform.listview.plusA.show();
mouseDragmove = true;
bx,by = win.toClient(winform.listview.plusA.hwnd,plusAkeydownPosX,plusAkeydownPosY);

}
}
}
}
}


winform.show()  
win.loopMessage();

不在注释了,和listbox一样的方式.

这里唯一要注意的是,listview鼠标事件要用listview.onnotify和listview.wndproc同时使用....有没有更简单的办法我是不知道了.

blob.png

上面是winform.listview.selIndex = 4; 这样的选择效果,那么我想实现类似鼠标点了一下那行 蓝色高亮显示,应该怎么做

blob.png


回复楼上的问题: 灰色因为listview失去了焦点导致,所以添加一个

winform.listview.setFocus();

就可以了.

上面的listview拖拽添加到拖动事件里面

case 0xFFFFFF93/*_LVN_BEGINDRAG*/{
//console.log("拖拽22222")
//先判断是否在有效行上点击

if(mouseLeftdown){
winform.listview.setFocus();
            var item = winform.listview.hitTest(plusAkeydownPosX,plusAkeydownPosY,true);
            .......


blob.png

blob.png

blob.png

blob.png



分层窗体的应用:

winform.transparent(true)

上面是对winform启用分层窗体并透明化..... 

运行后的结果就是啥也看不到,就是窗体全部透明了......只是在任务栏看到有这么个窗口...


那么如果在里面放入几个其他的控件,会怎么样子呢?

答案是:还是啥都看不到,就像空气....

那怎么才能显示出这些控件呢?

我们就需要把这些控件都脱离winform主窗体..

winform.plus.orphanWindow();
winform.edit.orphanWindow();

以上代码,使控件脱离主窗体,显示在窗体外部,但是仍然随着窗体变化..

那么效果呢?

GIF.gif

但是经过测试,发现如果主窗体里引用了其他窗体,比如custom控件里加载了另外一个winform,除非把这个custom利用orphanwindow()脱离mainform来显示winform可行, 如果winform里设置了透明度,但是在mainform中调用,这个透明度就会丢失....

GIF.gif

blob.png

转: 嵌入桌面并显示系统文件夹

import win.ui
import win.reg;
import web.form

/*DSG{{*/
var winform = ..win.form( bottom=398;parent=...;right=735;border="resizable";acceptfiles=1;cp=1;mode="popup";text="aardio Form";title=false )
winform.add( 
static={ dl=1;bottom=339;ah=1;right=704;left=6;dt=1;top=15;z=1;text="static";aw=1;edge=1;cls="static" }
)
/*}}*/

var wb = web.form(winform.static, 0x4/*_UIFLAG_NO3DBORDER*/ | 0x8/*_UIFLAG_SCROLL_NO*/);  
wb.go("C:\"); //打开C盘

var reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced");
var view = reg.queryValue("WebView");        
if( view = 1 ){
    winform.static.setPos(-213,0) 
    winform.static.width=winform.width + 205
    winform.static.height=winform.height-15        
}
else {
    winform.static.setPos(0,0)
    winform.static.width=winform.width -5
    winform.static.height=winform.height-5
}

win.setParent( winform.hwnd, win.find("progman") )

winform.show();
win.loopMessage();

所谓嵌入桌面,就是永远不会和其他窗口抢顺序,永远排在最后面...

如下图:中间那个就是嵌入桌面,最后面的是Q+桌面精灵,无论你点击桌面精灵还是点击嵌入的那个桌面,他们都不会跑到其他窗口前面去..

blob.png

设置控件透明度的方法:

下面的代码使窗体完全透明,然后按钮①脱离主窗体显示出来,旁边的按钮②因为在主窗体内部所以也被透明化,但是它的位置还在那,

当我点击按钮②,执行plus脱离主窗体,并半透明状态.

这里有个问题: 按钮①和②其实执行代码一样,但是点击按钮①并不会执行操作,只能点击在主窗体中的按钮②才会执行操作,为什么?

那么我执行完操作后,plus控件也脱离了主窗体,是不是意味着plus也收不到主窗体的操作了???

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=469;clipch=1)
winform.add(
button={cls="button";text="button";left=86;top=372;right=253;bottom=429;z=2};
button2={cls="button";text="button2";left=256;top=365;right=407;bottom=436;z=3};
plus={cls="plus";left=105;top=172;right=567;bottom=240;bgcolor=16711680;z=1}
)
/*}}*/

import console;
console.open();

winform.button2.oncommand = function(id,event){

winform.plus.orphanWindow();
winform.plus.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/)
::User32.SetLayeredWindowAttributes( winform.plus.hwnd,0, 100,2)

}
winform.button.oncommand = function(id,event){
winform.plus.orphanWindow();
winform.plus.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/)
::User32.SetLayeredWindowAttributes( winform.plus.hwnd,0, 100,2)

}

winform.button.orphanWindow();
winform.transparent(true);

winform.show() 
win.loopMessage();

blob.png

窗口开洞(透视)方法: 

开洞之后,不影响鼠标点击后面的窗体,例如,设置这个开洞了的窗体win.setTopmost(mainForm.hwnd)置顶. 鼠标在开了洞的地方点击,可以看到鼠标透过开洞窗体,点击到了后面的窗体上,就相当于真的在该窗体上开了个洞.

操作:

设置窗体背景色为0x000000黑色,那么在

mainForm.transparent(128,0x000000),设置过滤色是黑色即可.这样窗体就开了天窗.

如果设置的背景色为其他色,例如0xc0c0c0

那么过滤色也设置为它即可.

blob.png


接楼上,

如果我想在窗体上开洞,而不是整个窗体都变成洞,怎么办?

可以使用图片作为窗体的背景,然后过滤掉背景中想要开洞的颜色.

那么设计背景图的时候,就需要做一个对比度很高的图片,比如背景是白色,要掏的洞用黑色,保存为bmp位图.

然后将窗体背景图片设为此图片.

mainForm.transparent(128,0)
win.setTopmost(mainForm.hwnd)

然后为了避免拖动窗体的时候感觉卡,需要设置winform的背景属性:内部剪裁=true

这样运行的时候,黑色那块就透明了,而且鼠标也可以点击到后面的其他窗口...

那么如果我继续想改变开洞的大小,要怎么做?

这里就要用到九宫格切图了.

设置九宫格的框围绕那个黑色块,再次运行,拖动窗体边框开洞大小随着改变..

blob.png

blob.png

窗体开洞拍照功能演示:

利用desktop和com.picture.snap()功能:

import win.ui;
/*DSG{{*/
mainForm = win.form(text="aardio form";right=784;bottom=649;image=$"\res\zz.bmp";bgcolor=16777215;bkBottom=132;bkLeft=75;bkRight=89;bkTop=140;border="none";clipch=1)
mainForm.add(
button={cls="button";text="拍照并打开";left=498;top=551;right=701;bottom=627;color=-1;db=1;dr=1;font=LOGFONT(h=-21);z=1};
button2={cls="button";text="关闭窗口";left=267;top=551;right=470;bottom=627;db=1;dr=1;font=LOGFONT(h=-21);z=2};
static={cls="static";text="开洞抓拍演示:";left=81;top=51;right=356;bottom=94;color=8421376;dl=1;dt=1;font=LOGFONT(h=-32);transparent=1;z=3}
)
/*}}*/

mainForm.button2.oncommand = function(id,event){
//mainForm.msgbox( mainForm.button2.text );
mainForm.close();

}

mainForm.wndproc = function(hwnd,message,wParam,lParam){
select( message ) { 
case 0x201/*_WM_RBUTTONUP*/{
//鼠标右键弹起,下面获取坐标
mainForm.hitCaption()
}
}
}


import process ;
import gdip;

mainForm.button.oncommand = function(id,event){

import soImage;
var img = soImage();

var x,y,cx,cy = mainForm.getPos();//坐标 x , y  宽 高
//var pic = com.picture.snapClient(mainForm.hwnd,mainForm.bkLeft,mainForm.bkTop,cx-mainForm.bkRight-mainForm.bkLeft,cy-mainForm.bkBottom-mainForm.bkTop);
//var pic = com.picture.snapClient(win.getDesktop(),x+mainForm.bkLeft,y+mainForm.bkTop,cx-mainForm.bkRight-mainForm.bkLeft,cy-mainForm.bkBottom-mainForm.bkTop);
var pic = com.picture.snap(win.getDesktop(),x+mainForm.bkLeft,y+mainForm.bkTop,cx-mainForm.bkRight-mainForm.bkLeft,cy-mainForm.bkBottom-mainForm.bkTop);
//img.capture(mainForm.hwnd,mainForm.bkLeft,mainForm.bkTop,cx-mainForm.bkRight-mainForm.bkLeft,cy-mainForm.bkBottom-mainForm.bkTop);
//img.capture2(win.getDesktop(),x+mainForm.bkLeft,y+mainForm.bkTop,cx-mainForm.bkRight-mainForm.bkLeft,cy-mainForm.bkBottom-mainForm.bkTop);


var bmp = gdip.bitmap(pic,80);
bmp.save("/eb.bmp");
//img.save("/eb.bmp");
process.execute( "/eb.bmp" );


}
//窗体开洞
mainForm.transparent(128,0);

//win.setTopmost(mainForm.hwnd)
//添加阴影边框
import win.ui.shadow;
win.ui.shadow( mainForm,,20);
 
//下面的代码为窗体添加可拖动改变大小的边框
import win.ui.resizeBorder;
win.ui.resizeBorder( mainForm );

 
mainForm.enableDpiScaling();
mainForm.show();

return win.loopMessage();

QQ图片20171026154002.jpg

//桌面句柄
import winex;
var hDskManager,hShellView = winex.findExists("",,"<Progman>|<WorkerW>","SHELLDLL_DefView") 
win.show(hShellView,true);//显示桌面图标
win.show(hShellView,false);//隐藏桌面图标
横位置,纵位置 = win.getScreen();//取系统分辨率


//listview添加图标很简单,首先获取系统图像列表并绑定到listview控件
import win.ui;
/*DSG{{*/
var winform = ..win.form(text="listview显示图标";right=349;bottom=249)
winform.add(
listview={cls="listview";left=9;top=11;right=338;bottom=237;edge=1;mode="icon";z=1}
)
/*}}*/

//获取系统图标列表
import win.imageList;
shImageList = win.imageList.shell( 0/*_SHIL_LARGE*/  )
winform.listview.setImageList( shImageList,0/*_LVSIL_NORMAL*/ )

//获取文件图标索引
import fsys.info;
var filename = io._exepath; //要显示图标的文件路径
var sfi = fsys.info.get(filename, 0x4000/*_SHGFI_SYSICONINDEX*/ | 0x200/*_SHGFI_DISPLAYNAME*/)

//显示图标
winform.listview.addItem( { 
        text = sfi.szDisplayName;
        iImage = sfi.iIcon;
} ) 

winform.show() 
win.loopMessage();

blob.png

显示桌面上快捷方式的实际路径

import fsys;
import console;
import fsys.lnk;
 
var lnk = fsys.lnk();
fsys.enum( fsys.getSpecial(0 /*_CSIDL_DESKTOP*/ ) , "*.lnk",
        function(dir,filename,fullpath,findData){ 
                if(filename){ 
                        lnk.load(fullpath);
                   console.log("快捷方式:"+filename, "实际路径:"+lnk.path )
                } 
        },false
);
 
console.pause()

blob.png

import fsys;
import fsys.lnk;
import fsys.info;
//获取系统图标列表
import win.imageList;
shImageList = win.imageList.shell( 0/*_SHIL_LARGE*/  )
winform.listview.setImageList( shImageList,0/*_LVSIL_NORMAL*/ )

var lnk = fsys.lnk();
fsys.enum( fsys.getSpecial(0 /*_CSIDL_DESKTOP*/ ) , "*.lnk",
        function(dir,filename,fullpath,findData){ 
                if(filename){ 
                   lnk.load(fullpath);
                   //console.log("快捷方式:"+filename, "实际路径:"+lnk.path )
                   var sfi = fsys.info.get(lnk.path, 0x4000/*_SHGFI_SYSICONINDEX*/ | 0x200/*_SHGFI_DISPLAYNAME*/)
                   //显示图标
winform.listview.addItem( { 
         text = filename;//sfi.szDisplayName;
         iImage = sfi.iIcon;
} ) 
                } 
        },false
);

blob.png

窗体开洞抓拍+录制为gif动画:

import win.ui;
/*DSG{{*/
mainForm = win.form(text="aardio form";right=784;bottom=649;image=$"\res\zz.bmp";bgcolor=16777215;bkBottom=132;bkLeft=75;bkRight=89;bkTop=140;border="none";clipch=1)
mainForm.add(
button={cls="button";text="开始录制";left=291;top=548;right=494;bottom=624;color=-1;db=1;dr=1;font=LOGFONT(h=-21);z=1};
button2={cls="button";text="关闭窗口";left=70;top=548;right=273;bottom=624;db=1;dr=1;font=LOGFONT(h=-21);z=2};
button3={cls="button";text="结束录制";left=516;top=550;right=719;bottom=626;color=-1;db=1;dr=1;font=LOGFONT(h=-21);z=4};
static={cls="static";text="开洞抓拍演示:";left=81;top=51;right=356;bottom=94;color=8421376;dl=1;dt=1;font=LOGFONT(h=-32);transparent=1;z=3}
)
/*}}*/

 
import console;
console.open()
mainForm.button2.oncommand = function(id,event){
    //mainForm.msgbox( mainForm.button2.text );
    mainForm.close();
     
}
 
mainForm.wndproc = function(hwnd,message,wParam,lParam){
    select( message ) { 
        case 0x201/*_WM_RBUTTONUP*/{
            //鼠标右键弹起,下面获取坐标
            mainForm.hitCaption()  
        }
    }
}

mainForm.button.oncommand = function(id,event){
    thread.set("startOrend",true);
    
    thread.invoke(
        function( mainForm,caphwnd ){
            import com;
            import soImage;
            import console;
            //import win ;
            import win.ui ;
            //import process;
            var img = soImage();
            
            var gifFile = soImage.gifFile("/testgif.gif");
             
            while(thread.get("startOrend")){
             var x,y,cx,cy = mainForm.getPos();//坐标 x , y  宽 高
             //下面这句用上就会卡住界面,界面上的按钮就不能操作了
                //img.capture(win.getDesktop(),x,y,cx,cy);
                //于是换成了下面这个抓拍方式
                var pic = com.picture.snap(caphwnd,x+mainForm.bkLeft,y+mainForm.bkTop,cx-mainForm.bkRight-mainForm.bkLeft,cy-mainForm.bkBottom-mainForm.bkTop);
                //下面这两句多此一举了,pic可以直接获取句柄
                //var bmp = gdip.bitmap(pic,80); 
                //img.fromBitmap(bmp.copyHandle());
                //直接用下面这句handle
                img.fromBitmap(pic.Handle);
                gifFile.write(img,); //写入GIF文件
                console.log("已录制",gifFile.count())
                /**测试功能区-------
                //bmp.save("/eb.bmp");
         //img.save("/eb2.bmp");
        // process.execute( "/eb.bmp" );
                //thread.set("startOrend",false);
                --------------**/
               sleep(20);//50HZ
               //win.delay(20)
            }
            gifFile.close();//释放录制 
            console.log("录制完毕")
        },mainForm,win.getDesktop()
         
    )
 
}
 
mainForm.button3.oncommand = function(id,event){
    thread.set("startOrend",false);
}
 
 
 
 
//窗体开洞
mainForm.transparent(128,0);
 
//win.setTopmost(mainForm.hwnd)
//添加阴影边框
import win.ui.shadow;
win.ui.shadow( mainForm,,20);
  
//下面的代码为窗体添加可拖动改变大小的边框
import win.ui.resizeBorder;
win.ui.resizeBorder( mainForm );
 
  
mainForm.enableDpiScaling();
mainForm.show();
 
return win.loopMessage();

下面这张图片就是上面录制的结果,

录制过程中可移动,可放大缩小

testgif.gif

在Windows 2000/XP中,User32.dll增加了一个新函数SetLayeredWindowAttributes。要使用该函数,我们必须在生成窗口或使用SetWindowLong函数中设置窗口风格WS_EX_LAYERED (0x00080000)。该风格一旦被设置,我们就可以调用该函数来透明化窗口。该函数所需参数如下:

  • HWND hWnd: 窗口句柄

  • COLORREF col: 透明化颜色

  • BYTE bAlpha: =0:整个窗口透明, =255 完全不透明

  • DWORD dwFlags: =1:仅颜色 col 透明, =2 :窗口按照bAlpha变量进行透明处理。

代码 
首先定义对话框的成员变量(WinTransDlg.h)。

bool m_bTracking;   // 当鼠标被捕捉时设置为TRUE
HWND m_hCurrWnd;    // 鼠标所在窗口的句柄
HCURSOR m_hCursor;  // 棒型光标句柄

同时定义一个指向SetLayeredWindowAttributes函数的指针。该函数在User32.dll中定义。

// 全局变量
typedef BOOL (WINAPI *lpfn) (HWND hWnd, COLORREF cr, 
              BYTE bAlpha, DWORD dwFlags);


找到一种窗体开洞的另外一个办法:

  1. 设置窗体背景色, 假设为墨绿色

  2. 窗体上添加一个picture控件,背景色设置为黑色,

  3. mainform窗体属性中,内部剪裁设置为true

    blob.png

  4. 代码里添加


  5. mainForm.transparent(0,0)
    切记后面一个参数必需是0!!!!

调整picture的边框位置到窗口边缘,然后黑色就被透明了.

blob.png


blob.png

想要实现一个ide的拖拽调整大小和位置,点击控件之后出现调节的小点.....

转个基本功能方法:

import win.ui;
/*DSG{{*/
var winform = ..win.form( text="aardio Form";bottom=399;parent=...;right=599;border="resizable" )
winform.add(
static={ dr=1;dl=1;bottom=384;notify=1;right=584;left=16;dt=1;top=16;z=1;db=1;cp=1;edge=1;cls="static" }
)
/*}}*/

var imgGripper = 'GIF89a\x07\0\x07\0\x80\0\0\xFF\xFF\xFF\0\0\x80!\xF9\x04\0\0\0\0\0,\0\0\0\0\x07\0\x07\0\0\x02\x0C\x84o\xA1\x9A\x1B\xBD \x03\xEE\xA1S\0\0;';

winform.static.addCtrl(
    gripperTopLeft = { cls="picturebox";cur=0x7F82/*_IDC_SIZENWSE*/;notify=1;left=0;top=0;right=7;bottom=7;z=1;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperTop = { cls="picturebox";cur=0x7F85/*_IDC_SIZENS*/;notify=1;left=0;top=0;right=7;bottom=7;z=2;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperTopRight = { cls="picturebox";cur=0x7F83/*_IDC_SIZENESW*/;notify=1;left=0;top=0;right=7;bottom=7;z=3;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperLeft = { cls="picturebox";cur=0x7F84/*_IDC_SIZEWE*/;notify=1;left=0;top=0;right=7;bottom=7;z=4;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperRight = { cls="picturebox";cur=0x7F84/*_IDC_SIZEWE*/;notify=1;left=0;top=0;right=7;bottom=7;z=5;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperBottomLeft = { cls="picturebox";cur=0x7F83/*_IDC_SIZENESW*/;notify=1;left=0;top=0;right=7;bottom=7;z=6;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperBottom = { cls="picturebox";cur=0x7F85/*_IDC_SIZENS*/;notify=1;left=0;top=0;right=7;bottom=7;z=7;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
    gripperBottomRight = { cls="picturebox";cur=0x7F82/*_IDC_SIZENWSE*/;notify=1;left=0;top=0;right=7;bottom=7;z=8;image=imgGripper;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; }
);

import win.cur;
import win.graphics;

var selectedCtrl = null; // 当前选中控件
var gridSize = 8; // 网格大小

{
    var grippers = {
        winform.static.gripperTopLeft;winform.static.gripperTop;winform.static.gripperTopRight;
        winform.static.gripperLeft;winform.static.gripperRight;
        winform.static.gripperBottomLeft;winform.static.gripperBottom;winform.static.gripperBottomRight;
    };
    var messages = {
        0xD/*_HTTOPLEFT*/; 0xC/*_HTTOP*/; 0xE/*_HTTOPRIGHT*/;
        0xA/*_HTLEFT*/; 0xB/*_HTRIGHT*/;
        0x10/*_HTBOTTOMLEFT*/; 0xF/*_HTBOTTOM*/; 0x11/*_HTBOTTOMRIGHT*/;
    };
   
    for (i = 1; #grippers) {
        grippers[ i ].wndproc = {
            [0x200/*_WM_MOUSEMOVE*/] = function () {
                win.cur.setCur(win.cur.load(grippers[ i ].cur));
            }
            [0x201/*_WM_LBUTTONDOWN*/] = function () {
                return selectedCtrl ? ::SendMessageInt(selectedCtrl.hwnd, 0xA1/*_WM_NCLBUTTONDOWN*/, messages[ i ], 0);
            }
        };
    }
}

insertCtrl = function (name, options) {
    winform.static.addCtrl([name] = options);
   
    var adjustRect = function (rect, ...) {
        for (i, v in { ... }) {
            if (rect[v] % gridSize)
                rect[v] = math.round(rect[v] / gridSize) * gridSize;
        }
    }
   
    var ctrl = winform.static[name];
    ctrl.wndproc = function (hwnd, message, wParam, lParam) {
        select (message) {
            case 0x201/*_WM_LBUTTONDOWN*/ {
                ::SendMessage(owner.hwnd, 0x5/*_WM_SIZE*/);
                ::SendMessageInt(owner.hwnd, 0xA1/*_WM_NCLBUTTONDOWN*/, 2/*_HTCAPTION*/, 0);
                return 0;
            }
            case 0x5/*_WM_SIZE*/, 0x3/*_WM_MOVE*/ {
                var left = owner.left - 7;
                var top = owner.top - 7;
                var right = owner.right;
                var bottom = owner.bottom;
                var center = owner.left / 2 + owner.right / 2 - 3;
                var middle = owner.top / 2 + owner.bottom / 2 - 3;
               
                owner.setPos(, , , , 0x0/*_HWND_TOP*/);
                winform.static.gripperTopLeft.setPos(left, top, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperTop.setPos(center, top, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperTopRight.setPos(right, top, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperLeft.setPos(left, middle, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperRight.setPos(right, middle, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperBottomLeft.setPos(left, bottom, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperBottom.setPos(center, bottom, 7, 7, 0x0/*_HWND_TOP*/);
                winform.static.gripperBottomRight.setPos(right, bottom, 7, 7, 0x0/*_HWND_TOP*/);
               
                selectedCtrl = owner;
            }
            case 0x214/*_WM_SIZING*/ {
                var ptr = topointer(lParam);
                var rect = ::RECT();
                raw.convert(ptr, rect);
                if (wParam === 4/*_WMSZ_TOPLEFT*/ || wParam === 0x3/*_WMSZ_TOP*/ || wParam === 5/*_WMSZ_TOPRIGHT*/)
                    adjustRect(rect, "top");
                if (wParam === 4/*_WMSZ_TOPLEFT*/ || wParam === 1/*_WMSZ_LEFT*/ || wParam === 7/*_WMSZ_BOTTOMLEFT*/)
                    adjustRect(rect, "left");
                if (wParam === 5/*_WMSZ_TOPRIGHT*/ || wParam === 2/*_WMSZ_RIGHT*/ || wParam === 8/*_WMSZ_BOTTOMRIGHT*/)
                    adjustRect(rect, "right");
                if (wParam === 7/*_WMSZ_BOTTOMLEFT*/ || wParam === 6/*_WMSZ_BOTTOM*/ || wParam === 8/*_WMSZ_BOTTOMRIGHT*/)
                    adjustRect(rect, "bottom");
                ::CopyMemoryByStruct(ptr, rect, raw.sizeof(rect));
                return 1;
            }
            case 0x203/*_WM_LBUTTONDBLCLK*/ {
                return 0;
            }
        }
    }
   
    return ctrl;
}

{
    var buttonCount = 0;
   
    insertButton = function (x, y) {
        buttonCount++;
        return insertCtrl("button" + buttonCount, { cls="button";text="button" + buttonCount;left=x;top=y;right=x;bottom=y;style=0x4000000/*_WS_CLIPSIBLINGS*/;autoResize=0; });
    }
}

winform.static.wndproc = function (hwnd, message, wParam, lParam) {
    select (message) {
        case 0x201/*_WM_LBUTTONDOWN*/ {
            var button = insertButton(::LOWORD(lParam), ::HIWORD(lParam));
            ::SendMessageInt(button.hwnd, 0xA1/*_WM_NCLBUTTONDOWN*/, 0x11/*_HTBOTTOMRIGHT*/, 0);
            if (button.width <= 4)
                button.width = 100;
            if (button.height <= 4)
                button.height = 30;
            return 0;
        }
        case 0xF/*_WM_PAINT*/ {
            var cvs = win.graphics.canvas();
            cvs.beginPaint(owner.hwnd);
            cvs.brush.color = ::GetSysColor(0xF/*_COLOR_BTNFACE*/);
            cvs.fillRect(owner.clientRect);
            for (x = 0; owner.clientRect.right; gridSize) {
                for (y = 0; owner.clientRect.bottom; gridSize) {
                    cvs.setPixel(x, y, 0);
                }
            }
            cvs.endPaint();
            return 1;
        }
    }
}

winform.static.modifyStyle(, 0x2000000/*_WS_CLIPCHILDREN*/); // 防止闪烁

winform.show();
win.loopMessage();

blob.png

要回复文章请先登录注册