第十二章VB
6.0 Vbscript及Dll應用介紹
12.1前言
如果您需要在執行VB程式(延伸檔為*.exe)中加入某些陳述指令或自訂函數(Function)或次程序(Sub),如繪製2D函數或3D函數圖形時,需要輸入某特別之函數公式如f(x,y)=x^2+y^2-25;或z=5-Sqr(x^2+y^2)等,諸如此類問題,其應如何處理?微軟腳本稿(或稱原稿)控制項(Microsoft
Script Control)可以讓您輕鬆地達成任務。此項工作,我們稱之為自主應用(Host
application)。在程式執行階段使用腳本語言(Scripting language),可以是VBScript或JavaScript腳本語言,利用腳本控制項與VB執行程式溝通。您可以在腳本控制項中加入ActiveX物件(object),這些物件可以是表單、控制項、一般模組、類別模組,ActiveX動態程式庫(ActiveX
DLLs)或者是任意公有方法(public methods)、物件屬性(property
of the object) 或事件(Events)等。
所謂「腳本控制項」其實它就像一個巨集翻譯引擎,其可以在程式執行階段,將使用者所輸入之原始程式碼轉譯後傳遞給系統程式來執行。舉例來說,您可以在文字方塊中輸入一個函數,利用VBScript轉譯後,交由VB程式執行。在專案中使用腳本控制項應該先在「設定引用項目」及「設定使用元件」中勾選Microsoft
Script Control ,編寫腳本應該遵守腳本語法規定,尤其要特別注意在字串使用雙引號(")時,另外如要在文字方塊書寫程式碼應該將Multiline屬性設定成True。如要瞭解更多有關腳本資訊,可以上網下載Microsoft
Script Control腳本控制項相關文件。本章所介紹之Microsoft Script
Control觀念稍作休改作亦可適用在VB.NET,或將其利用VB.NET升級精靈直接升級至VB.NET。
(Vbscript control
大部份改編自TheScarms.com "Interpret Source Statement at Runtime & Expose Your
App's ObjectModel with the Scrpit Control")
12.2腳本控制項
下面是有關腳本控制項的屬性、方法及事件之簡略說明:
屬性(Property) |
說明(Description) |
AllowUI |
設定或傳回Boolean值以顯示程式執行中腳本或腳本控制項能否顯示使用者介面(User
interface)之訊息資料。在VBScript中如AllowUI設定為False,則MsgBox不起作用。 |
CodeObject |
傳回物件能用來呼叫公有成員(Public members)之特殊模組 |
Column |
傳回錯誤訊息以顯示腳本程式碼之大致位置 |
Description |
傳回錯誤訊息之簡單說明 |
HasReturnValue |
如果程序有回傳值,則HasReturnValue傳回真值(True);否則傳回False值 |
Language |
告訴腳本控制項自主程式是使用何種腳本語言,內定為VBScript,但亦可使用JScript |
Line |
傳回錯誤腳本原始碼之列位置 |
NumArgs |
傳回程序所需要之引數個數 |
Number |
傳回程序執行錯誤時之數值 |
Source |
傳回程序執行錯誤時之字串以表示錯誤型態 |
State |
在呼叫AddObject後,設定立即”連接”以啟動事件處理,如此您的腳本能對事件有所反應 |
Text |
傳回程序緒(Thread)執行時原始碼發生錯誤附近位置之片段字串 |
TimeOut |
當使用者選擇切斷或繼續執行腳本程序時,設定或傳回時間(單位為千分之一秒),如其值選用NoTimeout(常數值為-1);當TimeOut=0,則Timeout事件立即產生作用 |
UseSafeSubset |
設定或傳回Boolean值,以顯示自主應用是否安全,如UseSafeSubset值設定為真,則所有之物件及控制項都不能使用 |
方法(Method) |
說明(Description) |
AddCode |
在一般模組中新增腳本程式碼 |
AddObject |
在腳本引擎中建立執行階段之控制物件,AddObject為腳本控制項之使用者提供一組名稱/物件(name/object)能在腳本程式碼中使用 |
Clear |
清除所有錯誤物件之屬性,所有錯誤物件之屬性如執行階段當使用到AddCode,Eval,或ExecuteStatement等方法時,亦可利用重新設定(Reset)方法以清除錯誤物件 |
Eval |
回傳以數學公式(函數)表示之計算結果,Eval方法之使用語法(context)是由物件之引數(argument)決定,如果物件是模組,則造句語法僅限定為指名模組(named
module);如物件是腳本控制項,則造句語法是全域性的 |
ExecuteStatement |
執行特定之陳述句,ExecuteStatement方法之使用語法是由物件之引數(argument)決定,如果物件是模組,則造句語法僅限定為指名模組(named
module);如物件是腳本控制項,則造句語法是全域性的 |
Reset |
重新設定及初始化所有之腳本程式碼及腳本控制項 |
Run |
執行特定之程序 |
事件(Event) |
說明Description |
Error |
執行階段發生錯誤時觸發 |
TimeOut |
當Timeout屬性設定時間屆滿時觸發,或當使用者在對話方塊中選取End時觸發 |
12.3腳本控制項之應用
下面之為如何應用腳本控制項之例題說明的表單畫面。

1.輸入各別程序之原始碼,完整之程序或函數
2.在表單中預先建立腳本控制項之方法或屬性
3.在類別模組中預先建立自訂程序、自訂函數
4.如腳本程式碼發生錯誤時,應送出訊息及更正錯誤
根據巨集所使用的腳本語言,設定Script控制項的Language屬性。
在執行階段,用Script控制項的AddObject方法把應用程式裡的物件放進Script控制項中。這些物件可以是Private物件(如表單或Private物件類別),也可以是Public物件(如Public
ActiveX物件)。在執行階段,以Script控制項的AddCode物件方法載入巨集程序,載入後,用Script控制項的Run物件方法執行巨集程序。
使用Script控制項時,以下幾點你必須特別注意:
1.載入巨集是一個單向操作,你不能匯出已經載入Script控制項中的巨集。因此,如果你需要能夠改變巨集,必須把巨集放在外部的文字檔中。
2.你不能選擇性地釋放物件或巨集。必須用Reset方法釋放所有的物件和巨集,然後用AddObject和AddCode物件方法重新載入變更後的巨集或物件。
3.編譯時期錯誤會發生在Script控制項載入巨集時,而執行時期錯誤則發生在Script控制項執行巨集時。任何時候當你使用AddCode或Run方法時,都必須加入錯誤處理的程式碼。巨集所用到的物件方法若有接收字串的參數,必須以Variant型別宣告。
12.3.1如何寫入及執行腳本
下面我們將介紹兩種寫入腳本的作業方式,第一種將要加入之自訂函數Fxy()及程序Hello()直接在控制項中以腳本語言編寫;第二種是將已編輯完成之VB程式碼複製剪貼至文字方塊中,系統藉AddCode方法再由文字方塊取得程式碼。
(a)
直接在控制項中編寫腳本語言程式碼
直接在控制項中編寫程式碼所使用的語法和一般VB所使用的語法不同,要通知腳本控制項所使用的陳述句必須都用兩個雙引號包夾,每行後面以&
vbCrLf &或&Chr(13)
區隔。相關程式碼如下所示:
Dim sFunction As String
Dim sProcedure As String
'
sFunction = "Function
Fxy(x,y)" & vbCrLf & _ ‘兩個雙引號包夾部份為腳本稿
"Dim
Result " & vbCrLf & _
"
Result=x^2+y^2 " & vbCrLf & _
" Fxy =
Result " & vbCrLf & _
"End Function"
'
sProcedure = "Sub
Hello(sName)" & vbCrLf & _
" Msgbox
""Hello "" & sName " & _
"End Sub"
'
With ScriptControl0
‘腳本控制項名稱
.AddCode sFunction
.AddCode sProcedure
End With
下面為直接在控制項中編寫腳本語言程式碼測試之大致步驟:
1.開啟專案,並在程序cmdWithoutTextCode_Click(標題名稱:不使用文字方塊腳本)設定中斷點
2按下F5執行專案
3.按F8
鍵觀察剪貼之程式碼執行情形
(b)
複製剪貼其他文字編輯器所編寫VB程式碼
1.開啟專案,並在程序cmdWithTextCode_Click(標題名稱:(2)使用左側文字方塊腳本)設定中斷點
2按下F5執行專案
3將右側文字方塊中程序碼,複製剪貼左側文字方塊中,或直接點按「(1)複製右文字方塊」左側指令按鈕,將下列VB程序碼複製剪貼至左側文字方塊中。
Function Fxy(x,y)
Dim Result
Result = x^2+y^2
Fxy = Result
End Function
Sub
Hello(sName)
Msgbox "Hello " & sName
End Sub
4.按F8
鍵觀察剪貼之程式碼執行情形
12.3.2如何使用控制項
1.從清單方塊中反白選取任一個控制,假定選取Text1
2.點按
Expose the Text1物件指令按鈕
3.鍵入Text1之參考名稱如txt1或採取內定名稱Text1然後按「確定」鈕,假定
此處輸入為”txt1”
4.按Run
Script鈕後,會顯示表單所有控制項總數
5.在下面文字方塊中將原有文字清除後,鍵入可以操作文字方塊屬性的腳本文字如
txt1.visible=False
6.按Run
Script執行鍵,觀察表單如何變化(最上方文字方塊消失不見)
7.將txt1.visible=False清除改為txt1.visible=True,按Run
Script執行鍵觀察表單如何變化。
12.3.3
不使用ActiveX
控制項
前述各章節中,我們是需要在「設定引用項目」及「設定使用元件」中均需勾選「Microsoft Script
Control 1.0」。因為其已被直接引用到表單中,因此不必再設定為新物件,即其使用方式與一般VB預設控制項類似。如只在「設定引用項目」勾選「Microsoft
Script Control 1.0」,如要在表單引用時,則必須以New設定為實體物件,其語法為:
Dim
script_control As MSScriptControl.ScriptControl
Set
script_control = New MSScriptControl.ScriptControl
或
Dim
script_control As new MSScriptControl.ScriptControl
下面為使用MSScriptControl計算自定函數如Sind()的程式碼及執行後成果畫面。
Dim
myMath As New ClsmyMath '參考到類別ClsmyMath
Dim i
As Integer
Dim
name As String
Dim
value As String
Dim
rslt As Variant
'
建立腳本控制項.
Set
script_control = New MSScriptControl.ScriptControl
script_control.Language = "VBScript"
script_control.AddObject "myMath", myMath, True
'參考到類別ClsmyMath
Dim
nVar As Long
nVar = 0
For
i = 0 To 4
If
txtValue(i) = "" Then Exit For
nVar = nVar + 1
Next i
nVar = nVar - 1
For
i = 0 To nVar
script_control.AddCode txtVariable(i) & "=" & txtValue(i)
Next i
Dim
equation As String
equation = txtEquation
If
equation = "" Then equation = "x+y-4"
'
建立函數.
script_control.AddCode _
"Function TheFunction()" & vbCrLf & _
"TheFunction = " & equation & vbCrLf & _
"End Function"
'
計算.
txtResult.Text = ""
On
Error GoTo ErrHandler
rslt = script_control.Eval("TheFunction()")
txtResult.Text = Format$(rslt)
Exit Sub
ErrHandler:
Beep
MsgBox Err.Description

有或沒有VbScript控制項,在VB
6.0中使用,功能差異不大,但如升級至VB
NET,則差別就很大。唯升級至VB
NET後,有ActiveX控制項升級後必須手動修改的程式碼很繁雜,因此如要升級建議應該採用沒有ActiveX控制項者。下圖為VB
6.0升級(詳expr.net)後,偵錯後除出現升值提示(UPGRADE_NOTE:)後並無錯誤,唯在執行時發現錯誤訊息「InvalidCastException未處理(指定的轉換無效」並在Scrippt_control.AddObject(“myMath”,myMath,True)出現黃底標示,此因為類別ClsmyMath中出現系統無法偵錯出的錯誤所至,修正錯誤(詳expr.Net1)後即可重新執行。

12.4 VB 6
如何使用參考
在VB
6.0中專案(Project)可以參考引用其他同一個專案群組(Project
Groups)中的專案。其作業程序可歸案如下:
(1)
按一般程序建立一個新專案VB 6.0標準執行檔專案(EXE
Project:Project1或任何名程)後設計表單、控制項及編寫程式碼,儲存EXE專案名稱及表單名稱(同一個資料夾)。
(2)
在同一IDE作業環境下新增一個ActiveX
DLL動態連接資料庫(DLL
project:
Project2或任何名程)後編寫類別程式碼,儲存DLL專案名稱[必須與(1)同一個資料夾]。
(3)
開啟EXE
Project表單視窗後,執行「專案(P)\設定引用項目(R)…..」。在出現「設定引用項目
Project 1」對話方塊「可引用的項目中(A):」中反白選取Project
2後按「確定」鈕。

(4)測試程式無誤後,儲存「儲存專案群組(V)
,(與Project
1及2同一個資料夾)」。
12.5 VB 6
動態連接程式庫Dll製作
利用VB
6.0(中小企業版以上版本)製作動態連接程式庫(Dynamic
link library,Dll)一般多比利用VB
Net製作Dll複雜,尤其當VBscript需使用到Dll中之公有程序或函數時就更複雜。下面我們先介紹如何利用VB
6製作分數加減乘除四則運算動態連接程式庫的作業程序。
12.5.1製作ActiveX
DLL及註冊
利用VB
6.0製作ActiveX
DLL的作業程序,可簡單說明如下:
(1)
首先準備一份已測試完妥之類別模組(名稱為任意)
(2)
開啟VB
6程式,從「建立新專案」對話方塊中,選取「ActiveX
DLL」圖示。
(3)
將專案名稱從Project1改為DllFraction(任何名稱都可以)。
(4)
將類別模組名稱從Class1改為ClsFraction。
(5)
將下面分數四則運算程式碼複製剪貼至ClsFraction空白程式碼視窗中。
Option
Explicit
Dim
Num3 As Long, Den3 As Long
Public
Type Fraction
Num As
Long
Den As
Long
End
Type
Public Function
Add(Num1 As Long, Den1 As Long, Num2 As Long, Den2 As Long) As Fraction
If
(Den1 = 0 Or Den2 = 0) Then
MsgBox ("分母為0,請重來")
Exit Function
End
If
Num3 = Num1 * Den2 + Num2 * Den1
Den3 = Den1 * Den2
Reduce Num3, Den3
Add.Num = Num3
Add.Den = Den3
End Function
Public Function
Sbt(Num1 As Long, Den1 As Long, Num2 As Long, Den2 As Long) As Fraction
If
(Den1 = 0 Or Den2 = 0) Then
MsgBox ("分母為0,請重來")
Exit Function
End
If
Num3 = Num1 * Den2 - Num2 * Den1
Den3 = Den1 * Den2
Reduce Num3, Den3
Sbt.Num = Num3
Sbt.Den = Den3
End Function
Public Function
Mul(Num1 As Long, Den1 As Long, Num2 As Long, Den2 As Long) As Fraction
If
(Den1 = 0 Or Den2 = 0) Then
MsgBox ("分母為0,請重來")
Exit Function
End
If
Num3 = Num1 * Num2
Den3 = Den1 * Den2
Reduce Num3, Den3
Mul.Num = Num3
Mul.Den = Den3
End Function
Public Function
Div(Num1 As Long, Den1 As Long, Num2 As Long, Den2 As Long) As Fraction
If
(Den1 = 0 Or Den2 = 0) Then
MsgBox ("分母為0,請重來")
Exit Function
End
If
Num3 = Num1 * Den2
Den3 = Num2 * Den1
Reduce Num3, Den3
Div.Num = Num3
Div.Den = Den3
End Function
Private Function
Reduce(Num3 As Long, Den3 As Long) As Fraction
Dim
Stpt As Long
Dim
Ttpt As Long
Dim
Ptpt As Long
Stpt
= Abs(Num3)
Ttpt
= Abs(Den3)
If
Ttpt = 0 Then Exit Function
Do
Ptpt = (Stpt \ Ttpt) * Ttpt
Ptpt = Stpt - Ptpt
Stpt = Ttpt
Ttpt = Ptpt
Loop While Ptpt > 0
Num3 = Num3 \ Stpt
Den3 = Den3 \ Stpt
If
Den3 < 0 Then
Num3 = -Num3
Den3 = -Den3
End
If
Reduce.Num = Num3
Reduce.Den = Den3
End Function
(6)從「專案\DllFraction屬性(E),,,,」「DllFraction-專案屬性」頁中,將「編譯\DLL基底位址」中「DLL基底位址(B)」,從&H11000000
變更為&H11230000(前六碼為&Hxxxx,後四碼固定為0000。
(7)執行「專案\製成myFractionDll(K).…..」後按「確定」鈕。
(8)執行「執行\開始」,在「DllFraction-專案屬性」選取「啟動程式」方塊後,利用檔案瀏覽器打開存放DllFraction.dll的資料夾,然後在文字方塊檔案鍵入
「Regsvr32.Exe
DllFraction.dll」後按「確定」鈕,如執行成功,則在儲存myFractionDll.dll資料夾中會建立及註冊myFractionDll.dll。如註冊成功會出現「DllRegisterServer
在F;\dillfractionDay\dllfraction.dll成功。」訊息。

(9)另存專案至指定資料中(以後資料夾不要再任意更動),儲存檔案後關閉。
12.5.2建立測試專案
(1)在專案myFractionDll中,從功能表「檔案\新增專案」中,在相同IDE整合環境下開啟另外一個「標準執行檔」專案。
(2)將專案名稱改為myFractionTest,即在相同IDE中存在有myFractionDll及myFractionTest兩個專案。
(3)將下面之程式碼複製剪貼至myFractionTest表單空白程式碼視窗中。
Option
Explicit
Dim
Frac As New ClsFraction '宣告Frac為ClsFraction物件類別
Dim
Num1 As Long, Den1 As Long, Num2 As Long, Den2 As Long
Dim
Num3 As Long, Den3 As Long
Private Sub
cmdAdd_Click()
Picture1.Cls
Num1
= CLng(Val(txtN1.Text))
Den1
= CLng(Val(txtD1.Text))
Num2 =
CLng(Val(txtN2.Text))
Den2 =
CLng(Val(txtD2.Text))
Picture1.Print "a/b= "; Num1; "/"; Den1
Picture1.Print "c/d= "; Num2; "/"; Den2
Num3 =
Frac.Add(Num1, Den1, Num2, Den2).num
Den3 = Frac.Add(Num1,
Den1, Num2, Den2).den
txtN3.Text = Num3
txtD3.Text = Den3
Picture1.Print "(a/b)+(c/d)=e/f= "; Num3; "/"; Den3
End Sub
Private Sub
cmdDivide_Click()
Picture1.Cls
Num1 =
CLng(Val(txtN1.Text))
Den1 =
CLng(Val(txtD1.Text))
Num2 =
CLng(Val(txtN2.Text))
Den2 =
CLng(Val(txtD2.Text))
Picture1.Print "a/b= "; Num1; "/"; Den1
Picture1.Print "c/d= "; Num2; "/"; Den2
Num3 =
Frac.Div(Num1, Den1, Num2, Den2).num
Den3 = Frac.Div(Num1,
Den1, Num2, Den2).den
txtN3.Text = Num3
txtD3.Text = Den3
Picture1.Print "(a/b)/(c/d)=e/f= "; Num3; "/"; Den3
End Sub
Private Sub
cmdMultiply_Click()
Picture1.Cls
Num1 =
CLng(Val(txtN1.Text))
Den1 =
CLng(Val(txtD1.Text))
Num2 =
CLng(Val(txtN2.Text))
Den2 =
CLng(Val(txtD2.Text))
Picture1.Print "a/b= "; Num1; "/"; Den1
Picture1.Print "c/d= "; Num2; "/"; Den2
Num3 =
Frac.Mul(Num1, Den1, Num2, Den2).num
Den3 = Frac.Mul(Num1,
Den1, Num2, Den2).den
txtN3.Text = Num3
txtD3.Text = Den3
Picture1.Print "(a/b)*(c/d)=e/f= "; Num3; "/"; Den3
End
Sub
Private Sub
cmdSubtract_Click()
Picture1.Cls
Num1
= CLng(Val(txtN1.Text))
Den1
= CLng(Val(txtD1.Text))
Num2 =
CLng(Val(txtN2.Text))
Den2 =
CLng(Val(txtD2.Text))
Picture1.Print "a/b= "; Num1; "/"; Den1
Picture1.Print "c/d= "; Num2; "/"; Den2
Num3 =
Frac.Sbt(Num1, Den1, Num2, Den2).num
Den3 = Frac.Sbt(Num1,
Den1, Num2, Den2).den
txtN3.Text = Num3
txtD3.Text = Den3
Picture1.Print "(a/b)-(c/d)=e/f= "; Num3; "/"; Den3
End Sub
(4)
下面為測試表單樣式

(5)用滑鼠移至檔案總管視窗中myFractionTest圖示位置上點按右鈕,從下拉對話方塊中點選「設定為啟動專案」,將myFractionTest表單設定為啟動專案。
(6)執行「專案\設定引用項目」,在「設定引用項目」對話方塊中,利用檔案瀏覽器打開存放DllFraction.dll的資料夾,然後勾選myFractionDll。
(7)測試程式。




|