web库-web窗体

 

web窗体只能在「fap模拟程序」中使用,不能在「纯LAS脚本程序」中使用
请在「fap模拟程序」中新建脚本区块在脚本区块中添加LAScript脚本

一、HTML简介

网页使用HTML编写。
在网页上点右键打开菜单,选“查看源代码”就可以查看网页的HTML源代码。
HTML类似XML、ApeML语法。用「标签」(就是指被< >包起来的语法)来展现网页内容。
每个「标签」表示一个「HTML节点」,HTML节点可以嵌套包含。

<html>

    <head>
        <title>网页制作教学</title>
        <meta>
    </head>

    <body>
        body之间则为主要语法所在,也是网页的主要呈现部分。
        <img src="图片路径" />
        <a href="超链接网址">显示在网页上的超链接文字</a>

        下面是一个简单的登录表单:
        <form action="提交的目标网址" method="post">
            请输入用户名:<input name="username" type="text" />
            请输入密 码:<input name="password" type="password" />
        </form>

    </body>
</html>

以上看到的就是一篇最简单架构的网页。
一份完整的网页包含了二个部份:HTML头( <HEAD></HEAD )、网页内容( <BODY></BODY> )。
在HTML头的部份<HEAD></HEAD>中,有另一组子标签<TITLE></TITLE>。打在<TITLE></TITLE>这里面的文字就是网页的标题。

<input name="username" type="text" /> 是一个文本框控件,标签名为"input",name属性为"username" 。
input节点的「父节点」是form节点,form节点的「父节点」是body节点。

更多关于HTML的知识请参考网页制作的相关资料。

二、什么是web窗体

web窗体可以存取控制网页内容,并可以与网页内容进行交互,web窗体可以实现以下功能:

1、浏览并控制网页
使用web窗体可以显示网页,并自由读取、修改、控制网页内容。
通过LAScript控制web窗体,也可以通过web窗体调用LAScript。
通过web窗体,你可以使用任意网页编程方式,如javascipt,vbscript,甚至flash、ActiveX。
最重要的是,你不需要学习新的内容,只要会做网页就会轻松上手。

2、通过编写网页轻松完成GUI图形界面设计、创建漂亮的web窗体。
使用web窗体,你可以通过编写网页轻松实现自定义的程序界面。
可以使用所有网页制作技术,如javascipt,vbscript,甚至flash、ActiveX。
最重要的是,你不需要学习新的内容,只要会做网页就会轻松上手。
使用模拟精灵,你可以象vc、vb一样编写桌面程序,而且更方便、更简单。

三、创建web窗体

web窗体通常用一个userdata类型的变量来表示,可以使用下面的函数来创建新的web窗体。

wb = web.new()
wb = web();

创建空的web窗体,这个函数并不会初始化web窗体。
直到第一次使用web窗体才会自动初始化,例如打开网页、读取设置web窗体属性。

因为web.new 是web库的默认函数,web()等效于web.new();

wb = web.new(url)
wb = web(url)
url参数指定网址,创建新的web窗体并打开指定的网址。
如果为web.new函数指定网址参数,那么在创建web窗体以后会等待网页打开。
如果是一个远程网址自动设置为显示标题栏、滚动条。
如果是本地路径则自动设置为不显示标题栏、滚动条。

wb = web.new("about:blank")
wb = web("about:blank")
创建空的web窗体,初始化为无标题栏、无滚动条窗体。
通常用这个函数创建空的web窗体并使用wb:write函数写入网页内容。

四、释放web窗体

web.del(wb)
立即释放wb对象。并不会删除wb这个变量(wb指向无效的对象)。

wb = nil;
立即删除wb变量,等待垃圾收集释放wb引用的web窗体。

五、设置web窗体下载、控件显示、脚本执行的规则

web.setDL(wb,dl)
wb:setDL(dl)
可以设置web窗体下载、控件显示、脚本执行的规则,
这个函数必须在调用web.new()创建窗体以后立即调用,web.new函数不能带参数。
即在web窗体真正初始化以前web.setDL函数才有效。

web.setDL函数必须在调用web.new()创建窗体以后立即调用,web.new函数不能带参数。
即在web窗体真正初始化以前web.setDL函数才有效

例:

import("std");--在std.las中已经定义了_DLCTL_DLIMAGES _DLCTL_VIDEOS ......等变量。

wb = web.new()

wb:setDL( _DLCTL_DLIMAGES | _DLCTL_VIDEOS )
--允许显示图像与视频

wb:setDL( _DLCTL_NO_SCRIPTS | _DLCTL_NO_JAVA )
--不允许显示图像与视频,不允计执行脚本、不允许执行JAVA小程序

如果调用了wb:setDL函数,但是没有指定 _DLCTL_DLIMAGES | _DLCTL_VIDEOS 选项,则不会显示图像、视频。

如果希望禁用flash,应当在参数中添加 _DLCTL_NO_RUNACTIVEXCTLS | _DLCTL_NO_DLACTIVEXCTLS选项。


在我们使用模拟精灵做自动上网采集数据的机器人时,
我们可能不希望网页执行脚本、弹出很多对话框或网页、或者不希望下载多余的文件
那么我们可以使用这个函数设置web窗体。

在使用以前必须先声明需要用到的变量,如下:

_DLCTL_DLIMAGES = 0x00000010 --允许下载图像
_DLCTL_VIDEOS = 0x00000020 --视频
_DLCTL_BGSOUNDS = 0x00000040 --背景音乐
_DLCTL_NO_SCRIPTS = 0x00000080 --禁用脚本
_DLCTL_NO_JAVA = 0x00000100 --禁用JAVA小程序
_DLCTL_NO_RUNACTIVEXCTLS = 0x00000200 --禁止运行ActiveX 控件
_DLCTL_NO_DLACTIVEXCTLS = 0x00000400 --禁止下载ActiveX 控件
_DLCTL_DOWNLOADONLY = 0x00000800 --仅下载网页不显示
_DLCTL_NO_FRAMEDOWNLOAD = 0x00001000 --下载解析主框架页面,不会下载子框架。
_DLCTL_RESYNCHRONIZE= 0x00002000 --服务器将会被请求更新状态。如果服务器指出缓存信息是最新的,将会使用 缓存文件
_DLCTL_PRAGMA_NO_CACHE = 0x00004000 --不管文件的更新状态如何,文件都会被从服务器重新下载
_DLCTL_NO_BEHAVIORS = 0x00008000 --行为不被下载并且在文件中被禁用。
_DLCTL_NO_METACHARSET = 0x00010000 --忽略在META元素中指明的字符集
_DLCTL_URL_ENCODING_DISABLE_UTF8= 0x00020000 --禁止UTF-8 编码
_DLCTL_URL_ENCODING_ENABLE_UTF8 = 0x00040000 --允许禁止UTF-8 编码
_DLCTL_NOFRAMES = 0x00080000 --禁用框架
_DLCTL_FORCEOFFLINE = 0x10000000 --总是脱机模式
_DLCTL_NO_CLIENTPULL= 0x20000000 --不运行客户端重定位页面操作
_DLCTL_SILENT = 0x40000000 --在下载期间没有用户界面显示
_DLCTL_OFFLINEIFNOTCONNECTED= 0x80000000 --脱机模式
_DLCTL_OFFLINE = 0x80000000 --脱机模式

在std脚本库中已经包含了上面的定义,使用import("std")即可自动定义以上变量。

六、设置静默模式、不显示消息框

web.setSilent(wb,true|false,true|false,true|false,true|false)
wb:setSilent(true|false,true|false,true|false,true|false)
参数分别为(组件对话框静默,消息对话框静默,帮助对话框静默,下载对话框静默)
如果第四个参数设为true,则不会打开文件下载对话框。

静默模式指不显示用户界面、不弹出调试对话框、错误对话框、安全提示对话框、帮助对话框等

第一个参数设置是否开启组件静默模式。

第二个参数设定是否开启浏览器消息框静默模式,
如果设为true禁止提示对话框,用脚本弹出的对话框等。

第三个参数是否启用HTML帮助静默模式。

如果第四个参数设为true,则不会打开文件下载对话框。

例:

wb:setSilent(true,true,true,true);

七、禁止web窗体打开新窗口、弹出窗口

web.setOpen(wb,false)
wb:setOpen(false)
可以禁止web窗体打开新窗口、弹出窗口。

如果您希望所有页面都在当前web窗体中打开。
可以用下面的函数改变所有超链接与表单提交的目标为当前窗口。

--[[
可以使用web.linkSelf将web窗体上的所有链接改为在当前窗口打开(不弹出新窗口)
函数名: web.linkSelf 参数:(web窗体) 返回值:无
--]]
 
web.linkSelf = function( wb_page )
 
    links = { wb_page:eleForms(),wb_page:eleLinks() }

    --如果table构造器中使用了两组函数返回值,就必须用pairs迭代器
    for k,ele in pairs(links) do
        ele:setAttribute("target","_self")
        element.del(ele)
    end;
 
end;
 
-- ---------------------------------------
 
-- 用法示例
wb = web.new()
wb:setOpen(false)
wb:go("http://www.yhhe.com")
wb:wait("")
 
web.linkSelf(wb);
 
wb:show(true)

五、读写web窗体属性

hwnd = web.getWindow(wb)
hwnd = wb:getWindow()
读取的是web窗体的句柄

wb:getWindow() 等效于 web.getWindow(wb)
对象名后面使用冒号":"代替圆点"."作为函数成员符使用时,会自动添加一个self参数表示对象自身。

hwnd = web.getCtrl(wb)
hwnd = wb:getCtrl()
读取网页窗口的句柄。

-- 网页窗口的父窗口句柄即web窗体句柄。
win.getParent( wb:getCtrl() ) == wb:getWindow()

-- 如果在页面上执行javascript脚本"window.close();" 关闭页面
-- 则wb:getCtrl()返回nil空值


if( not wb:getCtrl() )then
wb = web.del(wb);
-- 页面已经关闭
end;

web.setScroll(wb,true|false)
wb:setScroll(true|false)
设置是否显示滚动条,必须在窗体显示以前设置
这个函数必须在调用web.new()创建窗体以后立即调用,web.new函数不能带参数。
即在web窗体真正初始化以前web.setDL函数才有效。

web.setScroll函数必须在调用web.new()创建窗体以后立即调用,web.new函数不能带参数。
即在web窗体真正初始化以前web.setScroll函数才有效。



web.setTitle(wb,true|false)
wb:setTitle(true|false)
设置是否显示默认的窗体标题栏(包含关闭按钮)

web窗体默认是不显示标题栏的,可以自行用网页设计标题栏。或者调用wb:setTitle(true)显示默认的标题栏。

页面的标题就是web窗体的标题 <title>标题内容</title> 在HTML的head部份
如果用VL设计的界面,可能要自已设标题。

wb = web.new("about:blank");
wb:setTitle(true); --显示标题栏
win.sendStringXX(wb:getWindow(),"这是web窗体的标题")

还有一种方法,就是自已用表格画一个标题栏,不要默认的标题栏( wb:setTitle(false) )
表格单元绑定属性 class="titlebar" 即可,最小化、最大化、关闭按钮分别绑定min max close等,
想画出什么样的标题栏都是可以的。

对于没有标题栏的web窗体,用鼠标点击web窗体,然后按ALT+F4即可关闭web窗体。

web.setMenu(wb,true|false)
wb:setMenu(true|false)
设置显示默认的右键菜单

url = web.location(wb)
url = wb:location()
读取web窗体当前URL

web.setFont(wb,num)
wb:setFont(num)
设置浏览器字体,这个函数必须在打开网页(如调用wb:go)以后调用。
可选参数如下:

_FONT_LARGEST = 4; --最大
_FONT_LARGE = 3; --大号
_FONT_MEDIUM =2; --中号
_FONT_SMALL = 1; --小号
_FONT_SMALLEST = 0; --最小

wb:setFont(_FONT_MEDIUM); --设置浏览器字体为中号

六、显示、隐藏web窗体

web.show(wb[,true|false|mode])
wb:show([true|false|mode]);

函数控制web窗体显示或隐藏。
参数设置为true显示,设置为false隐藏,其他可选项如下:

_SW_HIDE = 0
_SW_NORMAL = 1
_SW_SHOWMINIMIZED = 2
_SW_MAXIMIZE = 3
_SW_SHOWNOACTIVATE = 4
_SW_SHOW = 5
_SW_MINIMIZE = 6
_SW_SHOWMINNOACTIVE= 7
_SW_SHOWNA = 8
_SW_RESTORE = 9
_SW_SHOWDEFAULT = 10
_SW_MAX = 11

wb:show(_SW_MAX); --最大化web窗体
wb:show(_SW_HIDE ); --隐藏web窗体

mode参数的使用方法与 win.show 函数相同

七、打开网页

web.go(wb,"网址","目标框架","HTTP头","POST数据")
wb:go("网址","目标框架","HTTP头","POST数据")

用web窗体打开指定的网址,网址参数是必须的参数,其他的都是可选参数。

http头用\r\n分隔多个不同的键值对,post参数或者get参数用&分隔多个不同的键值对。

1、用web.go打开网页

wb:go("http://") --打开新的网址
wb:go(+1) --前进一页
wb:go(-1) --后退一页
wb:go(-2) --后退两页
wb:go(0) --刷新

2、使用POST自动提交表单


以POST方式发送数据主要是为了向服务器发送较大量的客户端的数据,它不受URL的长度限制。
POST请求将数据以URL编码的形式放在HTTP正文中,字段形式为fieldname=value,用&分隔每个字段。注意所有的字段都被作为字符串处理。

字符串值可以进行URL编码,模拟精灵提供URL编码、解码函数 web.encodeURL("") web.decodeURL("")

实际上我们要做的就是模拟浏览器POST一个表单。
参数为 wb:go(网址,目标窗口,需要重定义的HTTP头,post数据--string类型)

例:

wb:go("http://www.yhhe.net/ape/test/post.asp","_self","Content-Type: application/x-www-form-urlencoded","username=yihe&password=8970")


3、 使用multipart/form-data表单上传文件


如果要向服务器上传文件,我们就必须模拟一个POST multipart/form-data类型的请求,Content-Type必须是multipart/form-data。以multipart/form-data编码的POST请求格式与application/x-www-form-urlencoded完全不同,

multipart/form-data需要首先在HTTP请求头设置一个分隔符,例如ABCD:
wb:go("http://www.yhhe.net/ape/test/post.asp","_self","Content-Type: multipart/form-data; boundary=ABCD");
然后,将每个字段用“--分隔符”分隔,最后一个“--分隔符--”表示结束。

注意在LAScript中,字符串(string)是支持二进制的,例如上传test.txt:

wb = web.new("http://")
str = string.load("c:\\test.txt")
wb:go("http://www.yhhe.net/ape/test/post.asp?upload=true","_self","Content-Type: multipart/form-data; boundary=ABCD",[[--ABCD
Content-Disposition: form-data; name="name"
yihe
--ABCD
Content-Disposition: form-data; name="password"
8970
--ABCD
Content-Disposition: form-data; name="test.txt"; filename="C:\test.txt"
Content-Type: text/plain
]]..str..[[
--ABCD--
]])

--注意每个分隔符有后都有一个回车换行(\r\n);Content-Type前面有一个回车换行
--上面的写法等同于
wb:go("http://www.yhhe.net/ape/test/post.asp?upload=true","_self","Content-Type: multipart/form-data; boundary=ABCD","--ABCD\r\nContent-Disposition: form-data; name=\"name\"\r\nyihe\r\n--ABCD\r\nContent-Disposition: form-data; name=\"password\"\r\n8970\r\n--ABCD\r\nContent-Disposition: form-data; name=\"test.txt\"; filename=\"C:\test.txt\"\r\nContent-Type: text/plain\r\n"..str.."\r\n--ABCD--\r\n")
 
 
wb:show(true)

八、等待网页打开

web.wait(wb,"等待网址或网址的一部份",等待时间,是否刷新)
wb:wait("网址或部份网址",等待时间,是否刷新)

注意 函数如果在web.new参数中指定了网址则会自动调用web.wait等待页面打开,不需要再次调用 web.wait函数。
wb = web.new("http://www.yhhe.net");
wb:wait(""); -- 这句代码是多余的
如果执行了wb:go函数打开网页,在访问页面节点以前必须使用web.wait等待页面打开:
wb = web.new();
wb:setTitle(true); --启用标题栏
wb:go("http://www.yhhe.net");
wb:wait(""); -- 在调用wb:getEle访问页面节点以前,必须用wb:wait等待页面打开
ele = wb:getEle("");

所有参数都是可选参数,都可以忽略。
这个函数的作用是等待网页完全打开,只有网页完全打开才能访问网页的全部节点。

当执行 wb:wait() 时,web窗体首先检测当前是否正在打开网页。
如果网页已经下载完成就立即检测当前网址,如果检测符合指定的参数就立即返回nil值
否则,web窗体将一直等待,直到指定的网址下载完成。然后返回true真值。
如果在等待的过程中用户按了停止热键,则立即停止等待并返回nil值。

注意 wb:wait("网址") 参数中指定的网址不可以指定自动转向的网址,因为自动转向的网址有可能在页面全部下载前就转到别的网址了,这样wb:wait("可能自动转向的网址")就可能无法返回(直到用户按全部停止)

你可以使用以下几种方法调用本函数:

1、 指定等待的网址,注意大小写

wb:wait("http://www.yhhe.net")

2、指定等待的网址的一部份,注意大小写

wb:wait("http://")
wb:wait(".html")
wb:wait("www.yhhe.net")

3、 指定空值,只要页面下载完成就立即返回,不分析网址

wb:wait("")
wb:wait()

4、等待web窗体关闭

wb:wait(-1);

5、 在指定的等待时间内没有打开网页则自动刷新

wb:wait("网址或部份网址",15000);
--如果15秒内没有完全打开网页,则刷新网页

6、 在指定的等待时间内没有打开网页则返回nil空值

ok = wb:wait("网址或部份网址",15000,false);

例:

if(not wb:wait("网址或部份网址",15000,false) )then
--网页在15秒内没有成功打开。
end

7、自定义等待过程。

有时候模拟精灵提供的web.wait函数可能不能满足一些特定的要求。
例如有些网页打开很慢,等待网页完全下载可能是漫长的过程。

我们可以自已用while循环不断的检测需要的节点,如果这个节点已经下载就不再等待。
这样可以加快模拟程序的速度。

下面的web.waitEle函数就是执行这样一个功能。
web.waitEle可以替代web.getEle读取页面节点,而且不需要事先调用web.wait函数等待页面打开

--将下面的代码添加到fap模拟程序最前面的init区块中
--然后下面的函数替代wb:wait("") wb:getEle(elename)
do --创建一个语句块,在内部使用局部变量wb
    web.waitEle =  function(wb,elename)
        local ele;
        while( nStop() ) do --不断的循环,直到用用户按停止
            ele = wb:getEle(elename);
            if( ele ) then --如果取到了指定的节点
                break --中断循环
            end;
            delay(1000)
        end;
        return ele;
    end;
   
    local wb = web.new(); --创建一个web窗体对象以获取元表
    local meta = getmetatable(wb);   
    meta.waitEle = web.waitEle; --为web窗体对象添加waitEle函数
    web.del(wb);
end;
   
--用法示例
wb = web.new();
wb:go("http://www.yhhe.net");
ele = wb:waitEle("");
 
win.consoleOpen()
print(ele);

 

 

九、用web窗体创建模式对话框

str = web.doModal(wb,"本地路径")
str = wb:doModal("本地路径"))

wb:doModal打开并显示web页面,直到关闭web页面。
从页面中的userdata节点取得返回值(字符串),

九、读写web页面源代码

1、读取web窗体页面源代码

str = web.getHtml(wb)
str = wb:getHtml()
参数wb是一个web窗体对象。
这个函数读取打开页面时的原始HTML代码,
而不会读取页面发生改变后的HTML代码。

str = web.getBody(wb)
str = wb:getBody()
参数wb是一个web窗体对象。
读取网页body部份源代码。


wb:getBody()返回的是经过解析以后的HTML源代码,返回的源代码是忽略空格与换行的
wb:getHtml()返回的是最原始的网页文件源代码,返回的源代码不会自动忽略空格、换行等。


如果用web窗体打开xml文件,xml文件应用xsl并转换为网页。
用wb:getHtml()取不到转换后的HTML源代码,而使用wb:getBody仅能取到Body部份的源代码。

这时候我们可以用ele=wb:eleAll()取得页面全部HTML节点的第一个HTML根节点。
也就是<html> ... </html>,然后用ele:getHtml读取HTML源代码。

下面的init函数初始化一个web窗体来解析xml文件,并返回xml2html函数。
通过xml2html函数可以自动将xml文件转换为html文件。
function init() 
    local wb = web.new();   --init函数创建一个闭包保存局部变量wb
                                                  
    return  function(filename)  --返回一个匿名函数
        wb:go(filename);
        wb:wait("")
        local ele=wb:eleAll();
        assert(string.lower(ele:tag())=="html","第一个节点不是html节点");
        string.save(ele:getHtml() ,string.left( filename,#filename-3).."html");
        element.del(ele);
    end;

end;
 
xml2html = init();--初始化xml2html函数
 
xml2html("d:\\xml.xml")


2、向web窗体页面写入HTML代码


web.write(wb,"HTML代码",close)
wb:write("HTML",close)

向页面写入HTML代码,
close参数指定是否关闭输出流(可选参数可以省略,默认为true)。

wb:write("",true)
-- 写入HTML代码到页面,第一个参数指定写入内容,第二个参数指定自动关闭输出流)

wb:write("")
-- 同 wb:write("",true)

wb:write("",false)
-- 输出流不关闭,下次写入的内容自动追加到后面

wb:write()
-- 关闭输出流

十、读取element节点对象

element节点对象的使用方法请参考:element库

element对象是一个特殊的对象,没有element.new()函数可以创建对象,
只有element.del(ele)函数可以释放对象。

1、通过web.getEle读取element对象

ele = web.getEle(wb,"name or id");
ele = wb:getEle("name or id");
wb是一个web窗体对象,最后一个字符串参数指定节点的name属性或id属性。
读取HTML节点(element)对象,支持读取多个同名节点

失败返回nil值, 成功返回一个或多个element
例:

local wb = web.new();
wb:go("http://www.yhhe.net/ape/lib/")
wb:show(true);

win.messagePrint("正在打开网页,请稍候...")
wb:wait("");

local ele = wb:getEle("min")
if( ele )then
    win.messageBox("按钮min的源代码"..ele:getHtml(),"");
    element.del(ele);
end;

web.del(wb)

有多个同名的节点将返回一组element。例如:

ele,ele2,ele3 = wb:getEle("option name"); --多个返回值,无效的返回值赋予nil值
ele2:setAttribute("checked","true";
--选中第二个按钮

也可以用下面的方法把多个返回值转换为table

tele = { wb:getEle("option name"); } -- 将多个返回值放到{ }中转换为table数组
tele[2]:setAttribute("checked","true")

ele = web.getEle(wb,"");
ele = wb:getEle("");

读取body节点。

注意wb:getBody()仅读取body部份的源代码,而wb:getEle("")是返回一个element对象。

ele = web.eleFromPos(wb, x, y )
ele = wb:eleFromPos( x,y)
获取指定坐标的HTML节点对象,参数x,y指定HTML节点所在的屏幕坐标。

2、枚举节点列表、查找页面节点

tele = { web.eleAll(wb) }
tele = { wb:eleAll()}
读取页面上的全部HTML节点,全部返回值通过表构造器{}生成table数组。

tele = { web.eleLinks(wb) }
tele = { wb:eleLinks()}
读取页面上的全部超链接节点,全部返回值通过表构造器{}生成table数组。

读取页面的全部超链接,下面是一个例子
请在「fap模拟程序」中新建脚本区块在脚本区块中添加LAScript脚本
win.consoleOpen()

wb = web("http://www.yhhe.net")
links = { wb:eleLinks() }

for i,ele in pairs(links) do
    print(ele)
    print("标签",ele:tag())
    print("超链接",ele:getAttribute("href"))
    print("文本",ele:getTextin())
end;

web.del(wb)

delay( _CMD_LOOP )

tele = { web.eleImages(wb) }
tele = { wb:eleImages()}
读取页面上的全部图片节点,全部返回值通过表构造器{}生成table数组。

tele = { web.eleForms(wb) }
tele = { wb:eleForms()}
读取页面上的全部表单节点,全部返回值通过表构造器{}生成table数组。

tele = { web.eleScripts(wb) }
tele = { wb:eleScripts()}
读取页面上的全部脚本节点,全部返回值通过表构造器{}生成table数组。
脚本节点指使用<script> </script>标签建立的HTML节点。

下面是一个完整例子:

wb = web.new();

wb:go("http://www.yhhe.net");
wb:wait("");

--上面的三句代码可以简写为 wb = web("http://www.yhhe.net");

tab = { wb:eleAll() };
win.consoleOpen()
for i,ele in ipairs(tab) do
 print("发现节点:"..ele:tag() );
end;


3、在回调函数中能过参数获取HTML节点对象


--在 web.callProc 回调函数中,也可以通过第一个参数获取element对象
web.callProc = function(ele,wb)
    element.del(ele)
end;

4、在下载完成以前访问HTML节点。

通常在调用wb:go函数以后,在访问页面上的HTML节点以前,
我们需要调用wb:wait等待页面打开。

但是有的页面可能打开一大半却有极少的部份要等待很长时间才能下载完毕。
这样的页面在使用wb:wait时会导致漫长的待待。

我们可以不使用wb:wait而直接访问页面上的节点。
访问失败就继续等待,能取到我们需要的节点就不再等待。
下面是一个示例:

--[[ 参数说明
wb_t web窗体对象
ename 要查找的控件名字
s 等待的秒数
--]]

web.getEle2 = function(wb,ename,s)
    local ele;
    for i=1,s,1 do
        delay(1000);
        ele = wb:getEle(ename) ;
        if( ele )then
            return ele;
        end;
    end;
    return nil;
end;

wb = web.new("http://www.yhhe.net");
if(not web.getEle2(wb,"节点名字",3) ) then
    error("在3秒内没有找到有效的节点,出错了")
end;

 

十一、绑定页面标签

通过设置HTML标签的id属性值(或者class属性),指定可以与LAScript进行交互的对象
默认的ID一共有以下几个:

1、数据节点

id = "userdata"
这是一个特殊的节点,在页面必须是唯一的,一个web页面只能有一个userdata"节点

wb:doModal从userdata节点取得返回值(字符串),
当按下确定时,返回userdata节点,当按下取消或关闭时,返回空值
也可以在LAScript脚本中通过 web.setData web.getdata 存取userdata节点的值

web.setData(wb,str)
wb:setData(str)
设置userdata节点文本。

str = web.getdata(wb)
str = wb:getData()
读取userdata节点文本。

在HTML页面,可通过javascript语句:
document.all.userdata.innerText = "新值"
存取userdata节点的值

2、窗体控制节点,通过为按钮设置以下属性获取对WEB窗体的控制权
控制节点相同的可以有任意多个,如:可以把多个表格添加class = "titlebar" 属性使之成为标题栏

id = "ok"
--确定、返回userdata.innerText文本内容

id = "cancel"
--取消、返回空值

id = "close"
--关闭窗体

id = "min"
-- 最小化窗体

id = "minmax"
-- 最大化窗体/恢复窗体

id = "titlebar" 或 class = "titlebar"
--设置为标题栏,可拖动窗体,titlebar可以是一个td标签或span标签或者div标筌

id = "loadstring"
--用户点击以后,将读取userdata.innerText内容并作为LAScript语句执行

id = "call"
--自动调用web.callProc(val,hwnd) 函数,你可以重定义web.callProc以响应事件。

call是一个特殊的对象,他必须是一个按钮,id="call"的按钮可以有多个
在web.callProc回调函数中,你可以通过ele:getAttribute("value")判断用户点击的是哪一个按钮。

可以在LAScript中重定义web.callProc;
web.callProc函数原形如下:

web.callProc = function(ele,wb)
    --回调函数,参数(element对象,当前web窗体 )
end;

loadstring也是一个很有用的页面元素,下面是一个简单的示例:
<INPUT id="loadstring" type="button" onclick="javascript:document.all.userdata.innerText ='win.messageBox(\'我是LAScript脚本\',\'\')';" value="执行LASscript">
点击上面这个按钮,将会执行win.messageBox()函数,并弹出一个对话框。

十二、web窗体回调函数

1、下载完成回调函数

可以在LAScript中重定义web.loadProc;
web.loadProc函数原形如下:

web.loadProc = function(url,wb)
    --回调函数,参数(element对象,当前web窗体 )
end;

当一个网址重定向完成以后(无论成功或失败),自动调用 web.loadProc(url,wb)
其中url为当前网址,wb参数指向当前web窗体。

注意:你不可以在web.loadProc中调用web.del() 删除正在调用web.loadProc的web窗体。
如果这个窗体正在调用web.loadProc并且你在他返回之前就删除了他,那么模拟程序将会崩溃。
模拟精灵会自动检测这个错误并显示警告。


2、按钮回调函数

可以在LAScript中重定义web.callProc;
web.callProc函数原形如下:

web.callProc = function(ele,wb)
    --回调函数,参数(element对象,当前web窗体 )
end;

3、对话框回调函数 - 自动关闭网页上弹出窗口的方法


可以在LAScript中重定义web.msgProc ;
web.msgProc 函数原形如下:

web.msgProc = function(msg,wb)
    return 2; --返回要自动点击的对话框按钮ID(0为不点击),用录制功能查看按钮ID)
end;

其中msg参数是即消显示的消息内容,web参数指向当前web窗体。

返回值指定要点击的按钮ID。
用录制功能点击对话框上的按钮,即可以在“模拟区块-->锚点-->目标窗体-->控件ID”查看到按钮的ID
参考在web窗体上录制的方法。

也可以使用wb:setSilent(true,true,true,true)开启静默模式,禁止所有消息对话框,提示对话框,用脚本弹出的对话框(如alert)。

十三、怎样在WEB窗体上录制模拟区块

第一步:

在“脚本区块中”显示web窗体的代码后面加上 do return false end; --停止模拟程序

例:

wb = web.new("http://www.yhhe.net");
wb:show(true)
do return false end; --停止,录制完成以后,删除这句

第二步:

点击“回放运行”,在回放自动停止以后(即执行到 do return false end; )
点击录制热键(不是主界面的按钮)。然后就可以在WEB窗体上录制并创建锚点了。

注意不要按录制按钮(可以按浮动工具条上的绿色小三角按钮)因为在主界面点击录制按钮会自动隐藏web窗体。

十四、执行命令

web.exec(wb,cmd,val);
wb:exec(cmd,val);
在web窗体上执行命令。具体用法请参考: ele:exec 函数

十五、执行页面脚本

web.doScript(wb,str,"javascript")
web.doScript(wb,str,"vbscript")

wb:doScript(str,"javascript")
wb:doScript(str,"vbscript")
str参数指定脚本代码,最后一个参数指定脚本语言。

下面是一个例子,执行javascript脚本获取网页最后更新时间:
请在fap程序中新建一个脚本区块在脚本区块中添加以下脚本

function gettime(t)
    _t = t;
end;

wb = web.new("http://www.yhhe.net");
wb:doScript("var LAScript = external;LAScript.gettime(document.lastModified) ;","javascript")

win.messageBox( _t ,"网页最后修改时间")

十六、用web窗体设置信息窗口

模拟精灵在回放程序时会在屏幕左上角显示一个浮动窗口
使用win.messagePrint可以在浮动窗口中输出提示信息

现在我们用web窗体自已制作类似的信息提示窗口

wb = web.new("about:<div id='titlebar'>请进行一系列的操作,按这里可以拖动</div>");
wb:setRect(90,50,500,100);
 
wb:show(true)
 
--设置在最前面
win.topMost(wb:getWindow(), true);
 
delay(30000)
--进行一系列的操作
 
--关闭
web.del(wb);

上面是一个很简单的例子。
我们可能还需要通过wb:setRect函数设置web窗口的大小、位置。
添加关闭按钮等等。

系统默认有一种Marlett字体,实际上窗口上的关闭、最大化、最小化都是这种字体。
我们用Marlett字体的r字符显示关闭按钮。并通过添加id="close"设置这个表格单元为一个关闭按钮。

<td width="32" style="font-family: Marlett;font-size: 12pt;cursor:pointer" id="close">r</td>

使用网页的CSS样式表可以自由的设置外观,更改字体,字体颜色,还可以更改鼠标指针。
上面的示例在CSS中添加;cursor:pointer,则鼠标移动到关闭按钮上时会自动显示手形的指针。

我们设置fap模拟程序禁用信息窗口,然后重写win.messagePrint函数,
这样每次调用win.messagePrint的时候都会显示我们自已制作的信息窗口。

全部源代码如下:

function msginit()
    local html = [[
    <body style="margin-left: 0px;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;">
    <table id="bar" width="100%" border="0" cellpadding="2" cellspacing="0" style ="background-color: #99FFFF;">
    <tr >
    <td width="32" style="font-family: Marlett;font-size: 12pt;cursor:pointer" id="close">r</td>
    <td class="titlebar" ><div id='msg' style ="font-family: '宋体'; font-size: 9pt;"> 请进行一系列的操作,按这里可以拖动</div></td>
    <td width="32" align="right" style="font-family: Marlett;font-size: 12pt;">p</td>
    </tr>
    </table>
    </body>
    ]]
    local wb = web.new("about:blank");
    wb:write(html)
       
    local elebar = wb:getEle("msg");
    x,y,cx,cy = wb:getEle("bar"):getRect()
    wb:setRect(90,50,500,50+cy); --这里设定大小,左、上、右、下
   
    wb:show(true);
    win.topMost(wb:getWindow(), true);--设置在最前面
   
    win.messagePrint = function(msg)
        elebar:setTextin(tostring( msg ) );
        if(msg == "")then
            wb:show(false);
        else
           wb:show(true);
        end;
    end;
end;

msginit(); --初始化自定义的信息窗口
 
win.messagePrint("你好啊");

--下面是运行效果图

这仅仅是一个简单的例子,web窗体能轻松设计出多姿多彩的GUI界面。

十七、使用web窗体设计程序界面的简单例子

请在源码编辑器中输入下面的代码,并点击“生成模拟程序”

<?xml version="1.0" encoding="gb2312" ?>
<ApeML LID="CHS" MD="0" 抓屏模式="0" 名称="简单的web窗体" 作者="模拟精灵 2005" 信息窗口="true" 速度="10" 循环次数="1" 自定义属性="用户选项 = 0">
<!---->
<脚本区块 语言="LAScript" 名称="LAScript" 延时="0" 启用="true" 编辑密钥="" 运行公钥="">
<![CDATA[

html = [[

<html>
<head>
<title>web窗体</title>
<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<script>function SetButton(obj,state){ obj.className=(state == 0)?"buttonActive":"buttonNA";}</script>
<style> .titlebarx {filter:progid:DXImageTransform.Microsoft.Gradient(gradienttype=0, startcolorstr=#42BE42, endcolorstr=#FAFBDB);}
.toolbar {filter:progid:DXImageTransform.Microsoft.Gradient(gradienttype=0, startcolorstr=#F7F7F7, endcolorstr=#DEDBD6);}
.webform {filter:progid:DXImageTransform.Microsoft.Gradient(gradienttype=1, endcolorstr=#F7F7F7, startcolorstr=#DEDBD6);}
.caption { font-family: 宋体,Arial; font-size: 9pt; color: #000000; cursor: hand }
.minbutton {font-family: marlett; font-size: 10.5pt; }
th,td,body,span,div{ font-family: "宋体", Arial; font-size: 9pt; font-style: normal; line-height: 12pt; font-weight: normal; }
body { margin-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; background-color: #CCCCCC; }
.buttonNA { PADDING-LEFT: 4px; PADDING-RIGHT: 4px; CURSOR: hand;}
.buttonActive { PADDING-LEFT: 3px; PADDING-RIGHT: 3px; BACKGROUND-COLOR: #E7E7E7; BORDER: 1px solid #CCD0D9; CURSOR: hand; }
.buttonfloat { PADDING-LEFT: 4px; PADDING-RIGHT: 4px; CURSOR: hand;}
</style>
</head>
<body style="MARGIN:0px">
<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0" ID="Table1">
<tr height="1">
<th>
<table border="0" width="100%" id="table27" class="bodybar" cellspacing="0" cellpadding="0">
<tr>
<td><table width="100%" border="0" cellspacing="0" cellpadding="0" class="titlebarx" ID="Table2">
<tr>
<td class="titlebar" width="562" align="left">&nbsp;</td>
<td class="titlebar" width="224" align="right"><table border="0" cellspacing="0" cellpadding="0" height="22" ID="Table3">
<tr>
<td width="5"></td>
<td width="22" align="center" nowrap class="buttonNA" onMouseOver="SetButton(this,0)"
onMouseOut="SetButton(this,1)"><table border="0" cellspacing="0" cellpadding="0" ID="Table5">
<tr>
<td id="min" class="minbutton">0</td>
</tr>
</table>
</td>
<td width="5"></td>
<td width="22" align="center" nowrap class="buttonNA" onMouseOver="SetButton(this,0)"
onMouseOut="SetButton(this,1)"><table border="0" cellspacing="0" cellpadding="0" ID="Table6">
<tr>
<td id="minmax" class="minbutton" onClick="javascriopt:if(this.innerText=='1'){this.innerText='2';}else{this.innerText='1';}">1</td>
</tr>
</table>
</td>
<td width="5"></td>
<td width="35" align="center" nowrap class="buttonNA" onMouseOver="SetButton(this,0)"
onMouseOut="SetButton(this,1)"><table border="0" cellspacing="0" cellpadding="0" ID="Table7">
<tr>
<td id="close" class="minbutton">r</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td><table width="100%" border="0" cellspacing="0" cellpadding="0" ID="Table8">
<tr>
<th align="left">
<table width="100%" border="1" cellpadding="4" cellspacing="0" bgcolor="#f7f7f7" id="table28"
style="BORDER-COLLAPSE: collapse">
<tr>
<td class="toolbar"><table width="433" border="0" cellpadding="0" cellspacing="0" id="table29">
<tr>
<td nowrap><table border="0" width="2" cellspacing="0" cellpadding="1" id="table30">
<tr>
<td><img style="BORDER-RIGHT:1px inset; BORDER-TOP:1px inset; BORDER-LEFT:1px inset; BORDER-BOTTOM:1px inset"
height="1" width="1"></td>
</tr>
<tr>
<td><img style="BORDER-RIGHT:1px inset; BORDER-TOP:1px inset; BORDER-LEFT:1px inset; BORDER-BOTTOM:1px inset"
height="1" width="1"></td>
</tr>
<tr>
<td><img style="BORDER-RIGHT:1px inset; BORDER-TOP:1px inset; BORDER-LEFT:1px inset; BORDER-BOTTOM:1px inset"
height="1" width="1"></td>
</tr>
<tr>
<td><img style="BORDER-RIGHT:1px inset; BORDER-TOP:1px inset; BORDER-LEFT:1px inset; BORDER-BOTTOM:1px inset"
height="1" width="1"></td>
</tr>
</table>
</td>
<td nowrap class="caption">用户名</td>
<td nowrap><input name="usernae" type="text" class="textNA" onFocus='this.className="textActive";this.gf="1"'
onBlur='this.className="textNA";this.gf="0"' onMouseOver='this.className="textActive"' onMouseOut='if (this.gf=="0") this.className="textNA"' size="20"></td>
<td nowrap>密码</td>
<td align="left" nowrap><div align="left">
<input name="password" type="password" class="textNA" id="password" onFocus='this.className="textActive";this.gf="1"'
onBlur='this.className="textNA";this.gf="0"' onMouseOver='this.className="textActive"' onMouseOut='if (this.gf=="0") this.className="textNA"' size="20">
</div></td>
<td align="center" nowrap class="buttonNA" onMouseOver="SetButton(this,0)"
onmouseout="SetButton(this,1)"><table cellspacing="0" cellpadding="0" id="table31" width="39">
<tr>
<td nowrap></td>
<td class="caption">
<input name="call" type="button" id="call" value="登录"></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</th>
</tr>
</table>
</td>
</tr>
<tr>
<td height="5%">&nbsp;</td>
</tr>
</table>
</th>
</tr>
<tr>
<th height="100%">
<table width="100%" height="100%" border="0" cellpadding="5" cellspacing="5" ID="Table17">
<tr>
<th height="100%" align="left" valign="top" bgcolor="#ffffff">
<p>&nbsp;</p>
</th>
</tr>
</table>
</th>
</tr>
</table>
<span id="userdata" style="DISPLAY:none"></span>
</body>
</html>

]]

wb = web.new("about:blank"); --创建空的web窗体
wb:write(html);--写入HTML源代码
wb:show(true); --显示web窗体

wb:wait(-1);--等待web窗体关闭


]]>
</脚本区块>
<数据区块 />
</ApeML>