當(dāng)使用列表型變量作為參數(shù)時(shí),系統(tǒng)函數(shù)callscripticon的可選參數(shù)byvalue決定參數(shù)是以引用方式傳遞,還是以傳值方式傳遞。該參數(shù)的默認(rèn)值是false,表示參數(shù)以引用方式傳遞,圖標(biāo)變量args相當(dāng)于參數(shù)變量的別名,這意味著腳本函數(shù)可以修改參數(shù)變量的值。當(dāng)參數(shù)byvalue的值為true時(shí),authorware將參數(shù)變量的值復(fù)制到圖標(biāo)變量args中,腳本函數(shù)中所有對圖標(biāo)變量args的操作不會(huì)影響到參數(shù)變量本身。
系統(tǒng)函數(shù)callscripticon的另一個(gè)可選參數(shù)owner用于設(shè)置腳本函數(shù)的擁有者。在默認(rèn)情況下,調(diào)用腳本函數(shù)的運(yùn)算設(shè)計(jì)圖標(biāo)(即執(zhí)行系統(tǒng)函數(shù)callscripticon的運(yùn)算設(shè)計(jì)圖標(biāo))就是擁有者,這意味著由腳本函數(shù)繪制到【演示窗口中】的顯示對象都屬于該運(yùn)算設(shè)計(jì)圖標(biāo),通過【擦除】設(shè)計(jì)圖標(biāo)(或其他設(shè)計(jì)圖標(biāo)的自動(dòng)擦除選項(xiàng)以及系統(tǒng)函數(shù)eraseicon)擦除該設(shè)計(jì)圖標(biāo)就可以擦除由腳本函數(shù)繪制到屏幕中的對象。例如在圖3-41所示的流程中,執(zhí)行eraseicon(iconid@"call box")可以將窗口中顯示的所有矩形擦除,而執(zhí)行eraseicon(iconid@"box")則沒有任何效果。如果在調(diào)用腳本函數(shù)時(shí)總是將參數(shù)owner設(shè)置為true,即以callscripticon(@"box",,,1)方式調(diào)用腳本函數(shù),就將腳本函數(shù)的擁有者設(shè)置為對應(yīng)的【腳本函數(shù)】設(shè)計(jì)圖標(biāo)“box”,此時(shí)再執(zhí)行eraseicon(iconid@"box"),就可以擦除【演示】窗口中所有由腳本函數(shù)box繪制的矩形。
由調(diào)用者作為擁有者,就意味著由腳本函數(shù)輸出到演示窗口中的內(nèi)容可以被分別處理,不僅可以用擦除設(shè)計(jì)圖標(biāo)進(jìn)行單獨(dú)擦除,還可以用移動(dòng)設(shè)計(jì)圖標(biāo)進(jìn)行單獨(dú)移動(dòng),甚至單獨(dú)響應(yīng)用戶的操作。
腳本函數(shù)之間可以相互調(diào)用,也可以進(jìn)行遞歸調(diào)用(調(diào)用其自身)。這種相互調(diào)用存在一個(gè)最大次數(shù)的限制,因?yàn)橄到y(tǒng)函數(shù)callscripticon的參數(shù)棧是有限的,每個(gè)參數(shù)將會(huì)在棧中占據(jù)一定的位置,使用args參數(shù)將使遞歸調(diào)用的最大次數(shù)減半。同時(shí)使用4個(gè)參數(shù)將使遞歸調(diào)用的最大次數(shù)減少到1/4。當(dāng)達(dá)到棧的最大容量后,系統(tǒng)變量evalstatus和evalmessage將包含對應(yīng)的出錯(cuò)信息。遞歸調(diào)用的最大嵌套深度是12。
腳本函數(shù)的遞歸調(diào)用不是真正的遞歸調(diào)用,真正的遞歸調(diào)用意味著每層函數(shù)調(diào)用中所有的變量都是局部變量,而authorware中只存在全局變量,因此當(dāng)函數(shù)調(diào)用自身時(shí),當(dāng)前層中變量的值會(huì)被下一層調(diào)用中變量的值所覆蓋。所以,當(dāng)進(jìn)行遞歸調(diào)用時(shí),必須建立和維護(hù)腳本函數(shù)的變量堆棧,最簡便的方法是創(chuàng)建一個(gè)自動(dòng)增長的列表來保存每層函數(shù)調(diào)用中的變量值,當(dāng)每層函數(shù)調(diào)用返回時(shí)縮短列表的長度。如果在腳本函數(shù)中需要同時(shí)跟蹤多個(gè)變量的值,那么就要使用多維列表。
authorware沒有提供計(jì)算整數(shù)階乘的系統(tǒng)函數(shù)。以下是一個(gè)由aws編寫的腳本函數(shù)recursion,通過遞歸調(diào)用實(shí)現(xiàn)整數(shù)(12以內(nèi))的階乘。
-- nesting@"recursion"用于記錄當(dāng)前遞歸調(diào)用的嵌套深度
nesting@"recursion":=nesting@"recursion"+1
--由線性列表linearlist@"recursion"形成變量堆棧,保存每層調(diào)用中的args@"recursion"
--參數(shù)值。因?yàn)樵谙乱粚诱{(diào)用中,變量args@"recursion"值會(huì)發(fā)生變化
addlinear(linearlist@"recursion", args@"recursion", nesting@"recursion")
if args@"recursion">1 then
--n!=(n-1)!×n 在此不能直接使用變量args@"recursion",因?yàn)樵诤罄m(xù)的調(diào)用中它的值
--被改變。只能使用變量堆棧中保存的值。
result@"recursion":=callscripticon(@"recursion",args@"recursion"-1)* ﹁
linearlist@"recursion"[nesting@"recursion"]
else
result@"recursion":=1
end if
--退出本層遞歸過程之前,刪除無用的列表元素(相當(dāng)于將變量出棧)
deleteatindex(linearlist@"recursion", nesting@"recursion")
nesting@"recursion":=nesting@"recursion"-1
位于chapter03文件夾下的范例程序recursion.a7p提供了腳本函數(shù)recursion。如圖3-46所示,讀者可以在文本輸入框中輸入1至12之內(nèi)的整數(shù),回車之后就可以看到運(yùn)算結(jié)果。

圖3-46 范例程序recursion.a7p
現(xiàn)在以函數(shù)調(diào)用callscripticon(@"recursion",4)為例,通過參數(shù)和堆棧列表值的變化分析遞歸調(diào)用過程:
result:= callscripticon(@"recursion",4)
進(jìn)入第1層
linearlist@"recursion" [4]
nesting@"recursion" 1
args@"recursion" 4
result@"recursion" 0
進(jìn)入第2層
linearlist@"recursion" [4, 3]
nesting@"recursion" 2
args@"recursion" 3
result@"recursion" 0
進(jìn)入第3層
linearlist@"recursion" [4, 3, 2]
nesting@"recursion" 3
args@"recursion" 2
result@"recursion" 0
進(jìn)入第4層
linearlist@"recursion" [4, 3, 2, 1]
nesting@"recursion" 4
args@"recursion" 1
result@"recursion" 1
返回第3層
linearlist@"recursion" [4, 3, 2]
nesting@"recursion" 3
args@"recursion" 1
result@"recursion" 2
返回第2層
linearlist@"recursion" [4, 3]
nesting@"recursion" 2
args@"recursion" 1
result@"recursion" 6
返回第1層
linearlist@"recursion" [4]
nesting@"recursion" 1
args@"recursion" 1
result@"recursion" 24
最后返回計(jì)算結(jié)果24。
由于使用了堆棧,不要在腳本函數(shù)中使用goto()函數(shù)。可在正常退出腳本函數(shù)之后,再根據(jù)需要跳轉(zhuǎn)到其他設(shè)計(jì)圖標(biāo)。
創(chuàng)建多個(gè)腳本函數(shù)之后,就需要加強(qiáng)對腳本函數(shù)的管理,為每個(gè)腳本函數(shù)進(jìn)行必要的說明,如圖3-47所示,這樣就可以保證無論何時(shí)面對這些腳本函數(shù),都能夠保持清醒。同時(shí)還需要一種手段,可以方便地向設(shè)計(jì)圖標(biāo)中添加需要使用的腳本函數(shù)。通過為【腳本函數(shù)】設(shè)計(jì)圖標(biāo)添加描述信息可以實(shí)現(xiàn)上述目的。
在函數(shù)面板中【category】下拉列表框中選擇script icons類,在其中可以找到當(dāng)前程序中被創(chuàng)建的所有腳本函數(shù),在函數(shù)列表中選擇需要添加描述信息的腳本函數(shù)后,就可以向【description】文本框中輸入腳本函數(shù)的使用說明。注意將第一段內(nèi)容保持為腳本函數(shù)的完整使用語法(請參閱圖3-47)。
此后在函數(shù)列表中雙擊需要使用的腳本函數(shù),或者單擊函數(shù)面板的【paste】按鈕,就可以將該函數(shù)的使用語法粘貼到【運(yùn)算】窗口中當(dāng)前光標(biāo)所在位置處或者設(shè)計(jì)圖標(biāo)屬性檢查器中,就像使用系統(tǒng)函數(shù)一樣方便,如圖3-48所示。

圖3-47 為【腳本函數(shù)】設(shè)計(jì)圖標(biāo)添加描述信息

圖3-48 粘貼腳本函數(shù)
由于腳本函數(shù)只能通過系統(tǒng)函數(shù)callscripticon進(jìn)行調(diào)用,所以原則上【腳本函數(shù)】設(shè)計(jì)圖標(biāo)可以放在流程線上的任意位置而不會(huì)影響程序的正常運(yùn)行。但是在這里還是建議將所有的【腳本函數(shù)】設(shè)計(jì)圖標(biāo)集中放置在一起,以便于日后進(jìn)行維護(hù),如圖3-49所示。

圖3-49 集中管理腳本函數(shù)
腳本函數(shù)可以存儲(chǔ)在外部文本文件中。包含腳本函數(shù)的文本文件可以位于本地驅(qū)動(dòng)器,也可以位于網(wǎng)絡(luò)中(通過url指定地址)。將腳本函數(shù)存儲(chǔ)在外部文本文件中的真正意義在于,不同的程序文件可以共享同一份腳本函數(shù),同時(shí)便于進(jìn)行程序發(fā)行后的代碼維護(hù)。設(shè)計(jì)人員可以將最有可能發(fā)生改動(dòng)的代碼以外部腳本函數(shù)的形式保存在程序文件外部。
位于文本文件中的外部腳本函數(shù)必須通過系統(tǒng)函數(shù)callscriptfile()進(jìn)行調(diào)用,其使用語法為:
result:= callscriptfile("filename" [,args] [,byvalue])
與callscripticon()函數(shù)相比,callscriptfile()函數(shù)使用文本文件的路徑和名稱來代替【腳本函數(shù)】設(shè)計(jì)圖標(biāo)的名稱。
本書3.5.2節(jié)中介紹的字符串處理腳本函數(shù)都已經(jīng)被轉(zhuǎn)換為外部腳本函數(shù),分別存放在chapter03/scriptfiles文件夾下的6個(gè)文本文件之中。chapter03文件夾下的范例程序scriptfile.a7p示范了如何使用這些外部腳本函數(shù)。
以下是外部腳本函數(shù)sortchar.txt中的代碼(觀察與內(nèi)部腳本函數(shù)sortchar之間的區(qū)別):
charlist@iconid:=[]
result@iconid:=""
if listcount(args@iconid)>1 then
ascending@iconid:=args@(iconid)[2]
else if listcount(args@iconid)=1 then
ascending@iconid:=true
else
args@iconid:=list(args@iconid)
ascending@iconid:=true
end if
repeat with i@iconid:=1 to charcount(args@(iconid)[1])
addlinear(charlist@iconid, substr(args@(iconid)[1], i@iconid, i@iconid))
end repeat
sortbyvalue(charlist@iconid,ascending@iconid)
repeat with i@iconid:=1 to charcount(args@(iconid)[1])
result@iconid:=result@iconid^charlist@(iconid)[i@iconid]
end repeat
將內(nèi)部腳本函數(shù)轉(zhuǎn)換為外部腳本函數(shù)的要點(diǎn)在于:
(1)在使用各種圖標(biāo)變量時(shí),以@iconid代替@"sortchar"。忽略設(shè)計(jì)圖標(biāo)的名稱后,就可以在任意運(yùn)算設(shè)計(jì)圖標(biāo)中調(diào)用存儲(chǔ)于程序文件外部的腳本函數(shù)。
(2)對于列表型圖標(biāo)變量(例如args和charlist),由于下標(biāo)運(yùn)算符的優(yōu)先級(jí)高于引用運(yùn)算符,因此必須對iconid使用括號(hào),以類似于args@(iconid)[下標(biāo)]的方式訪問列表中的元素。
(3)必須為調(diào)用外部腳本函數(shù)的運(yùn)算設(shè)計(jì)圖標(biāo)創(chuàng)建函數(shù)中使用的所有圖標(biāo)變量。對于腳本函數(shù)sortchar而言,包含args,result,i,charlist和ascending,同時(shí)還要在程序文件范圍內(nèi)創(chuàng)建全局變量args,result,i,charlist和ascending,否則在調(diào)用腳本函數(shù)時(shí)會(huì)出現(xiàn)“variable is not defined.”的錯(cuò)誤提示信息。腳本函數(shù)中使用的全局變量也必須在程序文件范圍內(nèi)重新定義。
外部腳本函數(shù)sortchar.txt的調(diào)用方法是:
result:= callscriptfile(filelocation^"scriptfiles//sortchar.txt", [entrytext,0])
將腳本函數(shù)存儲(chǔ)在外部文本文件中可能會(huì)帶來一些安全問題:任何人都可以輕易地通過任意一種文本文件編輯工具查看外部腳本函數(shù)的內(nèi)容,從而了解程序運(yùn)行過程的細(xì)節(jié),或者惡意修改代碼,加入一些額外的指令。如果能夠?qū)⑼獠磕_本函數(shù)進(jìn)行加密,就能夠從很大程度上防止出現(xiàn)上述情況。
字符串腳本函數(shù)就是存儲(chǔ)有腳本函數(shù)的字符串。設(shè)計(jì)人員可以將字符串腳本函數(shù)加密后存儲(chǔ)于文本文件之中,在需要使用這些函數(shù)時(shí),將加密的函數(shù)代碼讀入字符串變量并進(jìn)行解密,還原為字符串腳本函數(shù),然后通過系統(tǒng)函數(shù)callscriptstring()對字符串腳本函數(shù)加以調(diào)用。
字符串腳本函數(shù)與其他類型腳本函數(shù)的主要區(qū)別在于,字符串腳本函數(shù)中只能使用全局變量。因此必須在程序文件范圍內(nèi)創(chuàng)建字符串腳本函數(shù)中用到的所有變量,否則在調(diào)用字符串腳本函數(shù)時(shí)會(huì)出現(xiàn)“variable is not defined.”的錯(cuò)誤提示。
以下是字符串腳本函數(shù)sortchar所包含的代碼(觀察與內(nèi)部腳本函數(shù)sortchar存在的區(qū)別):
charlist:=[]
result:=""
if listcount(args)>1 then
ascending:=args[2]
else if listcount(args)=1 then
ascending:=true
else
args:=list(args)
ascending:=true
end if
repeat with i:=1 to charcount(args[1])
addlinear(charlist, substr(args[1], i, i))
end repeat
sortbyvalue(charlist,ascending)
repeat with i:=1 to charcount(args[1])
result:=result^charlist[i]
end repeat
字符串腳本函數(shù)sortchar的調(diào)用方法是:
script:=readextfile("sortchar.txt")
args:=["authorware 7.0 is coming", 0]
callscriptstring(script ,args)
腳本函數(shù)的返回值存儲(chǔ)在全局變量result之中。
本書3.5.2節(jié)中介紹的字符串處理腳本函數(shù)都已經(jīng)被轉(zhuǎn)換為字符串腳本函數(shù),分別存放在chapter03/scriptstring文件夾下的6個(gè)文本文件之中。chapter03文件夾下的范例程序scriptstring.a7p示范了如何使用這些字符串腳本函數(shù)。
本書3.5.2節(jié)中介紹的encode腳本函數(shù)就是一個(gè)很好的加密函數(shù),利用它就可以將字符串腳本函數(shù)包含的代碼進(jìn)行加密。例如通過以下過程,就可以將存儲(chǔ)于wordreverse.txt文件之中的字符串腳本函數(shù)進(jìn)行加密,并保存在wordreverse_encrypted.txt文件之中。
script:=readextfile("wordreverse.txt")
encryptedscript:=callscripticon(@"encode",script)
writeextfile("wordreverse_encrypted.txt", encryptedscript)
打開wordreverse_encrypted.txt文件,只能看到一些雜亂無章的數(shù)字,如圖3-50所示。但是可以通過以下過程解密并調(diào)用字符串腳本函數(shù)。
script:=callscripticon(@"decode", readextfile("wordreverse_encrypted.txt"))
args:="authorware 7.0 is coming"
callscriptstring(script, args)

圖3-50 加密后的字符串腳本函數(shù)
本書3.5.2節(jié)中介紹的字符串處理腳本函數(shù)都已經(jīng)被轉(zhuǎn)換為加密的字符串腳本函數(shù),分別存放在chapter03/encryptedscript文件夾下的6個(gè)文本文件中。chapter03文件夾下的范例程序scriptstringencrypted.a7p示范了如何使用這些加密的字符串腳本函數(shù)。
新聞熱點(diǎn)
疑難解答