腳本函數(script function)是由設計人員利用aws自行編寫的函數,與代碼片段相比,腳本函數具有更加完備的功能。使用腳本函數就如同使用系統函數一樣,可以向腳本函數傳遞參數,或者接收腳本函數的返回值。通過將常用的過程(例如3.4節中介紹的常用字符串處理過程)定義為腳本函數,可以大大提高設計人員的開發效率。
腳本函數可以有3種存在形式:內部腳本函數、外部腳本函數和字符串腳本函數。
與創建代碼片段相比,創建腳本函數要稍微復雜一些,但是設計人員付出的這種努力會帶來大量的回報。代碼片段就像是預定義的宏,需要在程序中展開代碼才能進行工作,而腳本函數是真正的函數,其實現細節被封裝在【腳本函數】設計圖標內部,便于對代碼進行統一管理。設計人員可以隨時補充和完善腳本函數的功能,只要保證函數接口(參數和返回值)不發生變化,這些修改工作不會給程序中的其他內容帶來任何不利影響。
內部腳本函數存在于【腳本函數】設計圖標之中?!灸_本函數】設計圖標并不是一種新的設計圖標,而是運算設計圖標的一種新形式??梢酝ㄟ^以下步驟創建一個【腳本函數】設計圖標。
(1)向流程線上拖放一個運算設計圖標,并以所需函數名對運算設計圖標進行命名。該設計圖標名必須是惟一的,不能與其他設計圖標同名,但是可以與系統函數同名。現在將其命名為“box”。如圖3-38所示。
(2)執行modify>icon>properties菜單命令,打開運算設計圖標屬性檢查器,在屬性檢查器中打開contains script function復選框,將當前運算設計圖標定義為【腳本函數】設計圖標,如圖3-39所示。
(3)單擊屬性檢查器中的【ok】按鈕。此時運算設計圖標就變為【腳本函數】設計圖標,如圖3-40所示。此時設計圖標的外觀發生了變化。雙擊【腳本函數】設計圖標打開【運算】窗口,可以像使用普通運算設計圖標一樣向其中輸入代碼。向“box”運算窗口中輸入以下代碼:
repeat with i:= 1 to 100
box(1, 0, 0, i, i )
i:=i+1
end repeat
圖3-39 對運算設計圖標進行屬性設置
圖3-40 【腳本函數】設計圖標創建完畢
就創建了在【演示】窗口中繪制50個矩形這個簡單的腳本函數。
現在運行程序不會在【演示】窗口中看到任何矩形?!灸_本函數】設計圖標是一種特殊的【運算】設計圖標,它與普通【運算】設計圖標的不同之處在于:當程序執行到流程線上的腳本設計圖標時會略過它,并不自動執行其中的代碼。腳本函數只能通過系統函數callscripticon進行調用?,F在向【設計】窗口中添加一個【運算】設計圖標,如圖3-41所示,向“call box”設計圖標中輸入函數調用語句:
callscripticon(@"box")
就可以調用腳本函數box,在【演示】窗口中繪制矩形。由于authorware不會主動執行“box”設計圖標,因此兩個設計圖標的相對位置關系并不重要:將“call box”設計圖標放置在“box”設計圖標之前會得到同樣的運行結果。
對應的范例程序是chapter03文件夾下的scripticon-box.a7p。
圖3-41 調用腳本函數
與系統函數相比,腳本函數同樣可以具有參數和返回值??匆幌孪到y函數callscripticon完整的調用語法:
result:= callscripticon(iconid@"icontitle" [,args] [,byvalue] [,owner])
其中惟一的必選參數是【腳本函數】設計圖標的名稱??蛇x參數args就是向被調用的腳本函數傳遞的參數,該參數可以是各種類型,包括從最簡單的字符串類型到復雜的多維列表。腳本函數通過名為args的圖標變量來接受傳遞過來的參數,通過名為result的圖標變量返回執行結果。
例如要創建一個在【演示】窗口中隨機繪制多個矩形的腳本函數randombox,首先為其創建圖標變量args@"randombox",然后通過參數args指定繪制次數:
repeat with i:= 1 to args@"randombox"
--隨機挑選一種覆蓋模式
setmode(random(0,4,1))
--隨機設置邊框的顏色
setframe(1, rgb(random(0,255,1), random(0,255,1), random(0,255,1)))
--隨機設置填充顏色
setfill(1, rgb(random(0,255,1), random(0,255,1), random(0,255,1)))
--隨機設置矩形的位置和大小并進行繪制
box(random(1,8,1), random(1,windowwidth,1), random(1,windowheight,1),﹁
random(1,windowwidth,1), random(1,windowheight,1))
end repeat
在上述過程中,系統函數random()根據【演示】窗口寬度(windowwidth)和高度(windowheight),隨機決定矩形的大小、模式、顏色、位置和邊框,然后由系統函數box在屏幕中進行繪制。圖標變量args在這里決定了循環執行的次數,即繪制矩形的數目。在一個【運算】設計圖標中輸入以下函數調用語句,可以實現在【演示】窗口內部隨機繪制10個矩形的目的。
callscripticon(@"randombox ", 10)
程序流程和運行結果如圖3-42所示。接下來繼續創建兩個腳本函數:randomcircle和randomline,分別用于隨機繪制圓形和線段。
圖3-42 向腳本函數傳遞參數
--以下過程位于“randomcircle”設計圖標中
repeat with i:= 1 to args@"randombox"
setmode(random(0,4,1))
setframe(1, rgb(random(0,255,1), random(0,255,1), random(0,255,1)))
setfill(1, rgb(random(0,255,1), random(0,255,1), random(0,255,1)))
box(random(1,8,1), random(1,windowwidth,1), random(1,windowheight,1), ﹁
random(1,windowwidth,1), random(1,windowheight,1))
end repeat
--以下過程位于“randomline”設計圖標中
repeat with i:= 1 to args@"randomline"
setmode(random(0,4,1))
setframe(1, rgb(random(0,255,1), random(0,255,1), random(0,255,1)))
--隨機挑選箭頭樣式
setline(random(0,3,1))
line(random(1,8,1), random(1,windowwidth,1), random(1,windowheight,1), ﹁
random(1,windowwidth,1), random(1,windowheight,1))
end repeat
然后在【運算】設計圖標之中就可以通過以下函數調用語句,調用上述腳本函數開始繪圖:
callscripticon(@"randomcircle",10)
callscripticon(@"randomline",10)
腳本函數調用語句不必手工輸入。在創建新的腳本函數之后,函數面板中script icons類別下就會增加新的函數,如圖3-43所示。雙擊函數名稱,就可以直接將函數調用語句粘貼到【運算】窗口中,然后再根據需要補充調用參數就可以了。
圖3-43 新的函數
chapter03文件夾中的范例程序randomdraw.a7p演示了上述3個腳本函數的使用:如圖3-44所示,單擊【continue】按鈕,就可以在【演示】窗口中分別看到10個矩形、10個圓形和10條線段。
圖3-44 范例程序randomdraw.a7p
上述腳本函數中都使用了計數變量i,該變量屬于整個程序,而并非某個特定的腳本函數所有,任何設計圖標都可能使用該變量。為避免腳本函數和其他過程之間相互影響,應該在腳本函數中盡量使用圖標變量。
本節將3.4.3.2節中介紹的常用字符串處理過程轉換為腳本函數,并藉此介紹如何在腳本函數中處理變量和參數。
對于reverse過程,在將其改寫為腳本函數reverse時,除了利用圖標變量args@"reverse"接收準備處理的字符串參數(string)之外,還應該利用圖標變量result@"reverse"和i@"reverse"分別替換原有的變量result和i(result@"reverse"同時也作為腳本函數reverse的返回值):
result@"reverse":= ""
repeat with i@"reverse":= 1 to charcount(args@"reverse")
result@"reverse":= substr(args@"reverse", i@"reverse", i@"reverse")^ ﹁
result@"reverse"
end repeat
這樣就將腳本函數本身的數據封裝在腳本函數內部,因為上述圖標變量在腳本函數之外通常是不可見的。以后就可以通過函數調用語句:
result:= callscripticon(@"reverse", "authorware 7.0 is coming")
對腳本函數reverse進行調用,并將函數返回的結果"gnimoc si 0.7 erawrohtua"存儲到全局變量result之中。變量result@"reverse"和result之間互不影響。
實際上在【腳本函數】設計圖標之外仍然可以訪問圖標變量i@"reverse",但此時該變量的名稱已經非常明顯地告訴設計人員:這是一個僅僅屬于“reverse”設計圖標的變量。
按照類似的方法,可以將encode、decode、wordreverse和casereverse過程分別轉換為腳本函數。
--以下是腳本函數encode
result@"encode":= ""
repeat with i@"encode":= 1 to charcount(args@"encode")
ascii@"encode":= string(code(substr(args@"encode",i@"encode", i@"encode")))
reverse@"encode":= ""
repeat with j@"encode":= 1 to charcount(ascii@"encode")
reverse@"encode":= substr(ascii@"encode", j@"encode", j@"encode")^ ﹁
reverse@"encode"
end repeat
result@"encode":= result@"encode"^reverse@"encode"^" "
end repeat
腳本函數也可以互相調用。由于前面已經定義了具有反轉字符串功能的函數reverse,實際上可以將函數encode簡化為:
result@"encode":=""
repeat with i@"encode":=1 to charcount(args@"encode")
ascii@"encode":=string(code(substr(args@"encode", i@"encode", i@"encode")))
reverse@"encode":=callscripticon(@"reverse",ascii@"encode")
result@"encode":=result@"encode"^reverse@"encode"^" "
end repeat
但是為了在后續章節中能夠更好地描述各種腳本函數的工作方式,本書并沒有采用上述簡化代碼。
--以下是腳本函數decode
result@"decode":= ""
repeat with i@"decode":= 1 to wordcount(args@"decode")
ascii@"decode":= getword(i@"decode", args@"decode")
reverse@"decode":= ""
repeat with j@"decode":= 1 to charcount(ascii@"decode")
reverse@"decode":= substr(ascii@"decode", j@"decode", j@"decode")^ ﹁
reverse@"decode"
end repeat
result@"decode":= result@"decode"^ char(reverse@"decode")
end repeat
現在腳本函數便于調用的優勢已經凸顯出來,多次調用腳本函數encode,可以非常方便地對一個字符串進行多次加密,從而獲得較為理想的加密強度。
string:= "authorware 7.0 is coming"
--通過3次調用encode函數,對變量string的內容進行3重加密
repeat with i:= 1 to 3
string:= callscripticon(@"encode",string)
end repeat
--必須通過3次調用decode函數,才能對變量string的內容完全解密
repeat with i:= 1 to 3
string:=callscripticon(@"decode",string)
end repeat
函數encode并不是一個商業化的加密程序,它的作用僅僅是示范如何對字符串進行處理。不要使用它對同一字符串進行5次以上的加密,因為每次加密的結果都會以指數方式增長,很容易就會超出變量string的存儲容量(512kb)。
--以下是腳本函數wordreverse
result@"wordreverse":= ""
repeat with i@"wordreverse":= 1 to wordcount(args@"wordreverse")
result@"wordreverse":= getword(i@"wordreverse",args@"wordreverse")^" "﹁
^result@"wordreverse"
end repeat
result@"wordreverse":= substr(result@"wordreverse", 1, ﹁
charcount( result@"wordreverse")-1)
--以下是腳本函數casereverse
result@"casereverse":=""
repeat with i@"casereverse":=1 to charcount(args@"casereverse")
result@"casereverse":=result@"casereverse"^test(code(substr(﹁
args@"casereverse", i@"casereverse", i@"casereverse"))>64&code(substr(﹁
args@"casereverse", i@"casereverse" , i@"casereverse" ))<91, ﹁
lowercase(substr(args@"casereverse", i@"casereverse" , ﹁
i@"casereverse" )),(test(code(substr(args@"casereverse", i@"casereverse" , ﹁
i@"casereverse" ))>96&code(substr(args@"casereverse", i@"casereverse" , ﹁
i@"casereverse" ))<123, uppercase(substr(args@"casereverse", i@"casereverse" ,﹁
i@"casereverse" )),substr(args@"casereverse", i@"casereverse" , ﹁
i@"casereverse" ))))
end repeat
到目前為止這些腳本函數都只接收1個參數。從系統函數callscripticon的使用語法也可以看出,只能向腳本函數傳遞一個參數args。由于一個列表型變量可以包含多個元素,每個元素的值和數據類型也可以不同,因此可以將需要處理的多個數據集中放置在一個列表型變量中,再將該列表型變量作為參數傳遞給腳本函數,這就達到了向腳本函數傳遞多個參數的目的。
同理,如果將腳本函數設計為返回一個列表型變量,那么腳本函數實際上也能返回多個(種)值。
字符排序過程sortchar實際上需要使用兩個參數:string和ascending,前者是待排序的字符串,后者指定排序方式(升序或降序)。現在就為“sortchar”【腳本函數】設計圖標創建列表型變量args@"sortchar",通過它使腳本函數sortchar能夠接受兩個參數。
--以下是腳本函數sortchar
result@"sortchar":=""
charlist@"sortchar":=[]
ascending@"sortchar":=args@"sortchar"[2]
repeat with i@"sortchar":=1 to charcount(args@"sortchar"[1])
addlinear(charlist@"sortchar", substr(args@"sortchar"[1], i@"sortchar", ﹁
i@"sortchar"))
end repeat
sortbyvalue(charlist@"sortchar",ascending@"sortchar")
repeat with i@"sortchar":=1 to charcount(args@"sortchar"[1])
result@"sortchar":=result@"sortchar"^charlist@"sortchar"[i@"sortchar"]
end repeat
上述代碼中以粗體顯示的代碼是獲取第2個參數的語句。現在可以通過兩種方式調用sortchart函數:
string:= "authorware 7.0 is coming"
--對變量string中的字符串以降序排序
string1:= callscripticon(@"sortchart", [string, 0])
--對變量string中的字符串以升序排序
string2:= callscripticon(@"sortchart", [string, 1])
對函數sortchar中的粗體代碼進行修改,可以實現更為靈活的參數傳遞。例如可以將函數sortchar中第2個參數設置為可選參數,如果調用者沒有給出排序方式,則函數sortchar自動以升序方式排序。實現代碼如下所示:
-- ascending@"sortchar"的默認值為true,如果參數列表存在第2個元素,則以該元素
--指定排序方式
if listcount(args@"sortchar")>1 then
ascending@"sortchar":=args@"sortchar"[2]
else ascending@"sortchar":=true
end if
現在以下兩種函數調用方式是等價的(對變量string中的字符串以升序排序):
string1:= callscripticon(@"sortchart", [string])
string2:= callscripticon(@"sortchart", [string, 1])
可以通過以下代碼進一步拓寬參數的使用方式:
if listcount(args@"sortchar")>1 then
ascending@"sortchar":=args@"sortchar"[2]
else if listcount(args@"sortchar")=1 then
ascending@"sortchar":=true
else
--如果參數不是一個列表,則將其轉換為列表再進行處理
args@"sortchar":=list(args@"sortchar")
ascending@"sortchar":=true
end if
現在下列三種函數調用方式都是等價的。
string1:= callscripticon(@"sortchart", [string])
string2:= callscripticon(@"sortchart", [string, 1])
string3:= callscripticon(@"sortchart", string)
以下是腳本函數sortchar的最終版本:
result@"sortchar":=""
charlist@"sortchar":=[]
if listcount(args@"sortchar")>1 then
ascending@"sortchar":=args@"sortchar"[2]
else if listcount(args@"sortchar")=1 then
ascending@"sortchar":=true
else
args@"sortchar":=list(args@"sortchar")
ascending@"sortchar":=true
end if
repeat with i@"sortchar":=1 to charcount(args@"sortchar"[1])
addlinear(charlist@"sortchar", substr(args@"sortchar"[1], i@"sortchar", ﹁
i@"sortchar"))
end repeat
sortbyvalue(charlist@"sortchar",ascending@"sortchar")
repeat with i@"sortchar":=1 to charcount(args@"sortchar"[1])
result@"sortchar":=result@"sortchar"^charlist@"sortchar"[i@"sortchar"]
end repeat
讀者可能已經注意到這些腳本函數總是首先將圖標變量result的內容清空。這一操作是必需的,否則在下次調用腳本函數時,上次的調用結果將繼續參加下次的處理過程。
chapter03文件夾下的范例程序scripticon.a7p演示了這些腳本函數的功能。如圖3-45所示,讀者可以在演示窗口上方的文本輸入框中自由輸入字符串,然后單擊不同的按鈕調用腳本函數對輸入的字符串進行處理。注意在單擊encode按鈕后,才能使用decode按鈕對加密后的字符串進行解密,并且在單擊decode按鈕之前,其他按鈕處于禁用狀態。
圖3-45 范例程序scripticon.a7p
|
新聞熱點
疑難解答