9.連接Internet

V isual Basic可以建立三種在網頁瀏覽器上執行的Internet應用程式:

本章要介紹如何運用以上各種技術來建立多重網頁的應用程式。我們會用同一個範例來展示不同的應用程式,這些應用程式完整的原始程式碼都收錄在隨書光碟裡。

如何選擇Internet應用程式的種類?
 

在Internet的演進過程中,發展Internet應用程式的方式愈來愈多;Microsoft、Netscape、Sun Microsystems和其他公司都推出了相互競爭的發展工具,每一個公司都期待自己的產品可以成為業界的標準。然而到目前為止,我們仍然看不到一個單一的標準。

既然沒有標準可循,那麼發展應用程式就必須根據使用者本身的需求來選擇發展的方法。Visual Basic提供了四種發展Internet應用程式的方法,包括:使用ActiveX控制項和VBScript的HTML、DHTML、ActiveX文件以及IIS應用程式。你可以根據以下這幾個考慮因素,選擇你的發展方法:

 網頁瀏覽器 

如果你的應用程式必須能在Netscape Navigator和Internet Explorer中執行,你需要建立的是IIS應用程式,Netscape並不支援HTML中的ActiveX物件、VBScript、Microsoft版的DHTML和ActiveX文件。

 執行的位置 

IIS應用程式在伺服器上執行,這種方式適用於資料存放在伺服器的情況,但容易造成伺服器效率降低。ActiveX文件、DHTML和含有ActiveX物件的HTML都在用戶端電腦上執行,這些元件在執行前都必須先下載到用戶端電腦上。

 維護的簡易程度 

帶有大量文字資料的應用程式應選擇使用IIS、DHTML或是HTML,這些應用程式讓你可以把資料放在不同的檔案中,而不需重新編譯和散佈其可執行元件。ActiveX文件在經過內容的改變後,則必須重新編譯然後重新散佈至用戶端。

 對瀏覽器的控制程度 

ActiveX文件讓你可以控制瀏覽器的外觀並且可以不受限制地存取使用者的檔案系統。IIS、DHTML和HTML應用程式則無法改變瀏覽器而且檔案存取的能力也受到限制。

 安全性 

任何可執行的元件,諸如ActiveX文件或ActiveX控制項,都可以經由電子簽名而證明該文件不會破壞使用者的系統;然而,使用者可能會不願意接受陌生作者的電子簽名。IIS應用程式則沒有這方面的困擾,因為可執行碼都在伺服器上執行。

 未來的支援與標準 

Microsoft和Netscape目前各自支援不相容的DHTML,這種情況可能會在Navigator 5.0推出時獲得解決。Netscape也允諾Navigator 5.0將會支援ActiveX元件。

如果你正要發展一個在Internet上執行的應用程式,你的唯一選擇只有IIS應用程式,因為Netscape Navigator不支援其他種類的應用程式。如果你的應用程式要在企業內網路(Corporate Intranet)上執行,你就可以任選一種,因為在公司內部可以指定共同的瀏覽器。

Internet Explorer和Netscape Navigator在下一版時應該變得更能相容,這樣我們的顧慮就會少一些。然而,在還沒看到真正的產品之前,相容性是很難評估的。

如何建立DHTML應用程式?
 

在DHTML應用程式專案中,每一個HTML網頁都有一個DHTML設計師(DHTML Designer),這個專案還可以加入物件類別模組、程式碼模組、表單和其他可執行元件。專案經過編譯後,其可執行元件便會存放在DLL檔案裡,供應用程式中所有的HTML檔案引用。這種安排把網頁內容和可執行元件區隔在不同檔案裡。圖9-1所顯示的是設計階段中的Future Shock應用程式(DHFShock.VBP)。


 

 圖9-1 每一個DHTML設計師處理一個網頁

DHTML設計師提供的編輯功能十分有限,如果要用別的編輯工具,你需要把編輯器連上一個外部的HTML檔。怎麼做?在「屬性」視窗中選擇IDHTMLPageDesigner,然後在SourceFile屬性中選擇一個已經存在的HTML檔。當Visual Basic載入HTML檔之後,便可以在設計師視窗中按下工具列裡的「啟動編輯器」按鈕,開始編輯HTML檔。

以DHTML取得輸入的資料
 

為了使DHTML網頁中的元件可以被程式控制,你必須指定元件的ID屬性值;在相關的事件中出現在Visual Basic環境之前,提供這些事件的元件必須先擁有ID屬性值。在圖9-1的dhCalc設計師裡,每一個控制項都有一個ID屬性值,如以下的HTML檔所示:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN">
<HTML>
<HEAD>
<META content="text/html; charset=iso-8859-1" http-equiv=Content-
    Type><TITLE>Future Shock!</TITLE>
<META content=`"MSHTML 4.72.2106.6"` name=GENERATOR>
</HEAD>
<BODY bgColor=#ffffff>
<H1 id="">College Cost Calculator</H1>
<HR>
<P>Child's name: 
<INPUT id=txtName maxLength=20 name=sName> 
<P>Child's age: 
<INPUT id=txtAge maxLength=2 name=sAge size=2> 
<P>Type of college: <SELECT id=selCollege name=iCollege>
        <OPTION selected value=0>In-state public college
        <OPTION value=1>Out-of-state public college
        <OPTION value=2>Private college</SELECT>
<P>Type of transportation: <SELECT id=selTransport name=iTransport>
        <OPTION selected value=0>Bike
        <OPTION value=1>Bus
        <OPTION value=2>Used car
        <OPTION value=3>New car</SELECT>
<P>Type of housing: <SELECT id=selHousing name=iHousing>
        <OPTION selected value=0>Home
        <OPTION value=1>Dorm
        <OPTION value=2>Apartment</SELECT>
<P><INPUT id=butCalc type=button value=Calculate> </P></BODY></HTML>

這些ID屬性值使得Calculate按鈕能對滑鼠按鍵有所回應,並且可以讓你取得網頁上文字方塊和選項方塊中的資料。以下所列出的onclick事件程序會從dhCalc網頁中讀取資料,然後用Child物件計算子女上大學的成本:

Private Function butCalc_onclick() As Boolean
    Dim vntPayment, vntLumpSum, vntTotalCost
    Dim chdScholar As FutureShock.Child
    `Check fields for valid data
    If Len(txtName.Value) = 0 Or Len(txtAge.Value) = 0 Then
        BaseWindow.alert "You must enter name and age information."
        Exit Function
    End If
    `Create the Child object
    Set chdScholar = New FutureShock.Child
    `Set object properties
    chdScholar.Name = txtName.Value
    chdScholar.Age = txtAge.Value
    chdScholar.College = selCollege.Value
    chdScholar.Transport = selTransport.Value
    chdScholar.Housing = selHousing.Value
    `Calculate cost
    chdScholar.CollegeCost vntPayment, vntLumpSum, vntTotalCost
    `Set state properties so next page can get data
    PutProperty BaseWindow.Document, "Name", txtName.Value
    PutProperty BaseWindow.Document, "Payment", vntPayment
    PutProperty BaseWindow.Document, "LumpSum", vntLumpSum
    PutProperty BaseWindow.Document, "TotalCost", vntTotalCost
    `Display the results page
    BaseWindow.Navigate "dhResult.htm"
End Function

以DHTML顯示結果
 

Future Shock應用程式把用來顯示計算結果的網頁dhResult放在一個外部的dhResult.HTM裡,這樣,我們可以用一個外部的文字編輯器很方便地修改這個網頁。為了要使網頁瀏覽器載入dhResult.HTM,butCalc的onclick事件程序的最後必須要有這一行:

BaseWindow.Navigate "dhResult.htm"

如果把HTML原始碼存放在一個設計師檔(.DSR)中,你必須把上面的檔名加以修改,檔名前面必須加上專案名稱和一個底線符號(_)。下面這一段程式告訴你如何在兩個DHTML網頁之間相互切換。

`DHTMLPage1 code
Private Function Button1_onclick() As Boolean
    BaseWindow.Navigate "DHTMLProject_DHTMLPage2.HTML"
End Function

`DHTMLPage2 code
Private Function Button2_onclick() As Boolean
    BaseWindow.Navigate "DHTMLProject_DHTMLPage1.HTML"
End Function

在呼叫Navigate方法之前,請務必要用PutProperty方法保存所需的資料,以供另一個網頁使用。當一個網頁不顯示在瀏覽器上時,你就再也不能動用到其中的元件或是存取網頁中局部變數的資料。在Future Shock範例中,程式模組modDHTML包含著PutProperty和GetProperty物件方法。這個模組是在你建立DHTML專案之初自動產生的。

`PutProperty: 
`    Store information in a cookie by calling this
`    function.
`    The required inputs are the named Property
`    and the value of the property you would like to store.
`
`Optional inputs are:
`    expires : specifies a date that defines the valid 
`              life time of the property.  Once the expiration 
`              date has been reached, the property will no 
`              longer be stored or given out.

Public Sub PutProperty(objDocument As HTMLDocument, _
    strName As String, vntValue As Variant, _
    Optional Expires As Date)
     objDocument.cookie = strName & "=" & CStr(vntValue) & _
         IIf(CLng(Expires) = 0, "", "; expires=" & _
         Format(CStr(Expires), "ddd, dd-mmm-yy hh:mm:ss") & _
         " GMT") ` & _
End Sub

`GetProperty: 
`    Retrieve the value of a property by calling this
`    function.  The required input is the named Property,
`    and the return value of the function is the current value

`    of the property.  If the property cannot be found or has 
`    expired, then the return value will be an empty string.
`
Public Function GetProperty(objDocument As HTMLDocument, _
    strName As String) As Variant
    Dim aryCookies() As String
    Dim strCookie As Variant
    On Local Error GoTo NextCookie

    `Split the document cookie object into an array of cookies
    aryCookies = Split(objDocument.cookie, ";")
    For Each strCookie In aryCookies
        If Trim(VBA.Left(strCookie, InStr(strCookie, "=") - 1)) _
            = Trim(strName) Then
            GetProperty = Trim(Mid(strCookie, _
                InStr(strCookie, "=") + 1))
            Exit Function
        End If
NextCookie:
        Err = 0
    Next strCookie
End Function

當你要把某項結果和某行文字顯示在同一行時,可以用 <SPAN> 標籤;如果要顯示在不同行,你可以用 <DIV> 標籤。我們在dhResult網頁中以 <SPAN> 標籤標示了計算的結果,請看以下這段HTML碼:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN"> 
 <HTML> 
 <HEAD> 
 <META content="text/html; charset=iso-8859-1" http-equiv=Content- 
     Type><TITLE>Future Shock!</TITLE> 
 <META content=`"MSHTML 4.72.2106.6"` name=GENERATOR> 
 </HEAD> 
 <BODY bgColor=#ffffff id=""> 
 <H1>College Cost Calculator</H1> 
 <HR> 
 <P>Amount you need to invest today to pay for <SPAN id=spnName1>Name</ 
 SPAN> to  
 go to college: <SPAN id=spnLumpSum>LumpSum</SPAN>  
 <P>Amount you need to save each month to send <SPAN id=spnName2>Name</ 
 SPAN> to  
 college: <SPAN id=spnPayment>Payment</SPAN>  
 <P></P> 
 <P>Total amount you need to have by the time <SPAN id=spnName3>Name</ 
 SPAN> is  
 18: <SPAN id=spnTotalCost>TotalCost</SPAN>  
 <P><INPUT id=butBack type=button value="Go Back"> </P></BODY></HTML>

這些 <SPAN> 標籤的資料從何而來呢?我們在dhResult Document物件的onreadstatechanged事件程序中做了 <SPAN> 標籤與資料的代換。這個onreadstatechanged事件發生在網頁上的物件產生後但還沒有顯示之前。如果你利用DHTMLPage的Load或是Initialize事件來做這件工作,你會得到一個錯誤訊息,因為這些網頁上的元件這時都還尚未存在。

我們用InnerText屬性把 <SPAN> 標籤替換成實際的資料:

`This event occurs just before displaying the page
Private Sub Document_onreadystatechange()
    Dim vntName, vntPayment, vntTotalCost, vntLumpSum
    `Retrieve property values from modDHTML
    vntName = GetProperty(BaseWindow.Document, "Name")
    vntPayment = GetProperty(BaseWindow.Document, "Payment")
    vntTotalCost = GetProperty(BaseWindow.Document, "TotalCost")
    vntLumpSum = GetProperty(BaseWindow.Document, "LumpSum")
    `Display the value with <SPAN> tags
    With BaseWindow.Document
        .All("spnName1").innerText = vntName
        .All("spnName2").innerText = vntName
        .All("spnName3").innerText = vntName
        .All("spnPayment").innerText = vntPayment
        .All("spnTotalCost").innerText = vntTotalCost
        .All("spnLumpSum").innerText = vntLumpSum
    End With
End Sub

最後,dhResult網頁中最底下的按鈕用history物件的back方法讓你回到dhCalc網頁:

Private Function butBack_onclick() As Boolean
    `Go back to previous page
    BaseWindow.history.back
End Function

如何建立IIS應用程式?
 

IIS應用程式把內容放在Active Serve Page (ASP)裡。ASP是一種標準的文字檔,內含HTML碼和腳本程式碼(Scripts),副檔名為ASP。ASP檔案由Internet伺服器處理,執行時送出HTML碼到用戶端的網頁瀏覽器上。IIS應用程式的可執行元件存放在一個DLL檔案裡,這個DLL只能在Internet伺服器上面執行。Internet伺服器負責所有的處理運算工作,而用戶端瀏覽器則負責接收和發送純HTML格式的資料。從圖9-2中你可以看到這個運作模式。


 

 圖9-2 WebClass物件管理ASP中的物件

注意:

要建立一個IIS應用程式,你必須要在Windows NT上啟動IIS,或是在Windows 95上啟動Personal Web Server (PWS)。


在設計階段,IIS應用程式包含著一個WebClass設計師、幾個HTML範本檔案、物件類別模組和程式碼模組。IIS應用程式通常不會包含表單,因為表單只會顯示在伺服器上,而不會在用戶端。

建立一個新的IIS應用程式時,請在Visual Basic環境中選取「建立新專案」功能表選項,然後在對話方塊中點選兩下「IIS應用程式」圖像,Visual Basic會建立一個新的WebClass設計師,內含以下這段程式碼:

Private Sub WebClass_Start()
    Dim sQuote As String
    sQuote = Chr$(34)
    `Write a reply to the user
    With Response
        .Write "<HTML>"
        .Write "<body>"

        .Write "<h1><font face=" & sQuote & "Arial" & sQuote & _
               ">WebClass1's Starting Page</font></h1>"
        .Write "<p>This response was created in the Start " & _
               "event of WebClass1.</p>"
        .Write "</body>"
        .Write "</html>"
    End With
End Sub

從以上的程式中,你可以看到,我們用ASP Response物件把HTML碼寫到網頁瀏覽器中。如果你執行這個程式,Visual Basic會做以下這幾個動作:

  1. 如果專案目錄不存在,產生一個虛擬的專案目錄。
  2. 替WebClass產生一份ASP檔。
  3. 處理ASP檔,把結果送到用戶端的網頁瀏覽器中。

Visual Basic所產生的ASP會先確認WebClass管理員是否已經啟動,然後取得一個WebClass runtime的執行實體,最後產生一個你的WebClass的執行實體。以下這份ASP文件是為前面的WebClass所產生的:

<%
Server.ScriptTimeout=600
Response.Buffer=True
Response.Expires=0

If (VarType(Application("~WC~WebClassManager")) = 0) Then
    Application.Lock
    If (VarType(Application("~WC~WebClassManager")) = 0) Then
        Set Application("~WC~WebClassManager") = _
            Server.CreateObject("WebClassRuntime.WebClassManager")
    End If
    Application.UnLock
End If

Application("~WC~WebClassManager").ProcessNoStateWebClass _
    "Project1.WebClass1", _
    Server, _
    Application, _
    Session, _
    Request, _
    Response
%>

有一點必須提醒你,ASP檔本身並不負責把資料送到用戶端的瀏覽器,這個動作由WebClass的可執行碼負責。這是Visual Basic 6與Visual Basic 5的IIS應用程式的差異。

  • 在Visual Basic 5裡,要用HTML在ASP檔中寫出使用者界面,然後在同一個檔案中用VBScript引用伺服器物件。
     
  • 在Visual Basic 6中,可以在WebClass裡用Write和WriteTemplate方法把HTML碼寫到用戶端的瀏覽器裡,而伺服器物件已經在WebClass裡準備就緒了。
     

以下幾節將要介紹如何用WebClass取得使用者輸入的資料,做完處理之後送出資料給使用者。

顯示HTML樣版
 

從前面的WebClass的程式碼中,你可以看到Response物件的Write物件方法被用來將HTML碼送到網頁瀏覽器裡;這種傳送資料的方式適用於簡單的例子,如果要傳送大量的HTML碼便顯得沒有效率了。幸好,Visual Basic讓你可以用HTML範本的方式把HTML檔案加入到WebClass裡。

若要把一個HTML檔案加到WebClass裡,請在WebClass設計師視窗中點選「加入HTML Template WebClass Item 」按鈕。圖9-3顯示的是一個包含著兩個HTML範本的WebClass。以下就是htmCalc的HTML碼:

<HTML>
<HEAD><TITLE>Future Shock!</TITLE></HEAD>
<BODY BGCOLOR=#FFFFFF>
<H1>College Cost Calculator</H1>
<HR>
    <FORM METHOD="POST" NAME="frmCalc">
    <P>
    Child's name: <INPUT TYPE=TEXT SIZE=20 MAXLENGTH=20 
        NAME="strName">
    <P>
    Child's age: <INPUT TYPE=TEXT SIZE=2 MAXLENGTH=2 
        NAME="strAge">
    <P>
    Type of college:
    <SELECT NAME="optCollege">
        <OPTION VALUE=0>In-state public college
        <OPTION VALUE=1>Out-of-state public college
        <OPTION VALUE=2>Private college
    </SELECT>
    <P>
    Type of transportation:
    <SELECT NAME="optTransport">
        <OPTION VALUE=0>Bike
        <OPTION VALUE=1>Bus
        <OPTION VALUE=2>Used car
        <OPTION VALUE=3>New car
    </SELECT>
    <P>
    Type of housing:
    <SELECT NAME="optHousing">
        <OPTION VALUE=0>Home
        <OPTION VALUE=1>Dorm
        <OPTION VALUE=2>Apartment
    </SELECT>
    <P>
    <INPUT TYPE="SUBMIT" VALUE="Calculate" NAME="butCalc">
</FORM>
</BODY>
</HTML>

要從WebClass裡把HTML範本顯示出來,你要用Write Template物件方法。例如,如果你要在WebClass啟動時顯示htmCalc,你應該用底下這段程式:

Private Sub WebClass_Start()
    `Display the calculator page
    htmCalc.WriteTemplate
End Sub

上面這段程式執行的結果如圖9-4。


 

 圖9-3 WebClass包含著兩個HTML範本


 

 圖9-4 htmCalc範本的HTML表單界面

以IIS取得輸入的資料
 

要取得由htmCalc範本收到的資料,你必須把某個事件程序與某個HTML表單的動作關聯在一起,然後再加入程式碼,取得表單上欄位的資料。請看以下這幾個步驟:

  1. 在WebClass設計師視窗的左半邊,點選含有HTML表單的範本。
  2. 在設計師視窗的右半邊,以右鍵點選表單的名稱(frmCalc),叫出一個快顯功能表。
  3. 從快顯功能表中選取「檢視程式碼」。Visual Basic會建立一個事件程序(如果原來沒有的話),然後把這個程序和表單的預設事件關聯在一起。

注意:

WebClass只對瀏覽器送給伺服器的事件有所反應,例如送出表單中的資料或是要求一份網頁資料;其他事件,如HTML的Buttton物件的onclick事件,只發生在瀏覽器上,不會影響WebClass。如果要WebClass對瀏覽器上的事件作出反應,必須在網頁上加上VBScript的事件程序。


要取得HTML表單上的資料,必須用Request物件的Form物件集合。每一個Form物件集合裡的項目都對應到HTML表單上的一個元件,這些元件都以HTML範本上的Name屬性做為辨識的依據。例如,以下這段程式從HTML表單上的欄位中獲得資料,經過計算後把結果透過範本顯示出來:

Private Sub htmCalc_frmCalc()
`Check for valid data
    If Len(Request.Form("strName")) = 0 Or _
        Len(Request.Form("strAge")) = 0 Then
        Response.Write "<p>Name and age are required.</p>"
        Exit Sub
    End If
    `Create an object variable
    Set mchdScholar = New Child
    `Get form data
    With Request
        mvntName = .Form("strName")
        mchdScholar.Name = .Form("strName")
        mchdScholar.Age = .Form("strAge")
        mchdScholar.College = .Form("optCollege")
        mchdScholar.Transport = .Form("optTransport")
        mchdScholar.Housing = .Form("optHousing")
    End With
    `Calculate costs
    mchdScholar.CollegeCost mvntPayment, mvntLumpSum, mvntTotalCost
    `Write result; triggers ReplaceToken event
    htmResult.WriteTemplate
End Sub

注意:

DHTML應用程式以ID屬性辨識物件,而WebClass則用Name屬性作為辨識的依據。


以IIS顯示計算的結果
 

從網頁上收集的資料經過處理後,下一步就是將結果透過瀏覽器顯示出來。要在瀏覽器上顯示結果,最簡單的方式是用Response物件的Write方法。以下這段程式把前一節中程式計算的結果顯示在瀏覽器上。

Private Sub htmCalc_frmCalc()
    `Code omitted here (same as previous section)Dear John, How Do 
    I... 
        Dim sQuote As String
        sQuote = Chr$(34)
        `Write result using Response.Write
        With Response
            .Write "<HTML>"
            .Write "<body>"
            .Write "<h1><font face=" & sQuote & "Arial" & sQuote & _
                   ">Results</font></h1>"
            .Write "<p>The cost of sending " & mvntName & _
                   " to college is: " & mvntTotalCost & "</p>"
            .Write "</body>"
            .Write "</html>"
    End With
End Sub

如果你必須把大量的文字顯示在瀏覽器上,另一個更好的方式是以WriteTemplate方法顯示HTML範本。你可以把範本中的變數以 <WC@> 和 </WC@> 標識,如以下這段HTML碼:

<HTML>
<HEAD><TITLE>Future Shock!</TITLE></HEAD>
<BODY BGCOLOR=#FFFFFF>
<H1>Results</H1>
<HR>
Amount you need to invest today to pay for <WC@>strName</WC@> to 
go to college: <WC@>LumpSum</WC@>.
<P>
Amount you need to save each month to send <WC@>strName</WC@> to 
college: <WC@>Payment</WC@>.
<P>
Total amount you need to have by the time <WC@>strName</
WC@> is 18: <WC@>TotalCost</WC@>.
<p> <WC@>htmCalc</WC@>Go Back.</a>
</FORM>
</BODY>
</HTML>

在Visual Basic將範本送給瀏覽器之前,它會檢查樣版中哪一個標籤應以實際的資料予以取代。如果Visual Basic檢查到這種標籤,它便會啟動Process Tag事件。以下這段程式以Select Case指令讓實際的資料取代HTML範本中的變數標籤:

Private Sub htmResult_ProcessTag(ByVal TagName As String, _
    TagContents As String, SendTags As Boolean)
    `Remove extra spaces and carriage returns-seems to be
    `a bug in webclasses
    TagContents = Trim(TagContents)
    TagContents = Replace(TagContents, vbCrLf, "")
    `Replace strings in template
    Select Case TagContents
        Case "strName"
            TagContents = mvntName
        Case "Payment"
            TagContents = mvntPayment
        Case "LumpSum"
            TagContents = mvntLumpSum
        Case "TotalCost"
            TagContents = mvntTotalCost
        Case "htmCalc"
            `Create a link back to htmCalc
            TagContents = "<a href=" & GetURL(htmCalc) & ">"
        Case Else
    End Select
End Sub

`Return the URL for a WebItem
Function GetURL(htmObject As Object) As String
    Dim strURL As String
    `Get the URL (includes extra stuff)
    strURL = urlfor(htmObject)
    `Strip off the non-URL text
    strURL = Mid(strURL, 1, InStr(1, strURL, "?") - 1)
    `Return the result
    GetURL = strURL
End Function

Visual Basic在每次遇到該被取代的變數標籤時都會驅動ProcessTag事件,你可以一步一步地追蹤程式碼,觀察其運作方式。當程式執行到最後,HTML資料就會顯示在瀏覽器上,如圖9-5。


 

 圖9-5 以IIS顯示HTML樣版

如何建立ActiveX文件應用程式?
 

AcitiveX文件應用程式以Visual Basic的使用者文件(User Document)來對發生的事件作回應動作以及呈現資料,使用者文件和表單很類似,但是使用者文件與表單之間有下列重大差異:

  • 在使用者文件中的資料,不能讓應用程式其他的部分讀取。你不能在使用者文件的外部引用文件中的屬性。
     
  • 以使用者文件發展的應用程式需要透過Internet Explorer來執行,因此,不能單獨地只用Visual Basic環境來進行偵錯的工作。
     
  • 經過編譯的應用程式一定要從HTML檔案中啟動,這個HTML檔案在顯示Visual Basic文件檔(VBD檔)之前會載入應用程式的程式元件。因此,不能從Visual Basic環境中直接啟動執行檔;即使在Internet Explorer中,你也必須透過這個特定的HTML才能看見VBD檔。
     

以下這幾個小節將會介紹上述的差異。

從ActiveX文件中取得輸入的資料
 

Future Shock應用程式(AXFShock.VBP)是用來計算培養一個孩子上大學所需花費的成本,它包含了兩個使用者文件,如圖9-6,udCalc文件(udCalc.DOB)用來收集讓孩子唸大學的成本資料,udResult (udResult.DOB)則用來顯示計算的結果。

為了要達到資料共享的目的,這兩份使用者文件必須依賴一個全域範圍的物件gchdScholar,它被宣告在一個DECLARES.BAS模組中,如下所示:

'Global object that shares data between
'user documents
Public gchdScholar As New Child

gchdScholar物件變數引用一個Child物件類別的物件執行實體,Child物件類別被定義在CHILD.CLS物件類別模組裡。Child物件類別中包括了在udCalc文件中所有資料欄的屬性。我們用udCalc文件來設定Child物件類別中的屬性值,當使用者按下Calculate按鈕之後,計算的結果便會由udResult文件加以顯示。

在程式偵錯階段,我們希望Internet Explorer從磁碟中讀取編譯後的使用者文件(VBD檔),這樣會比較方便程式的偵錯及修改;一旦程式完成之後,我們就必須讓Internet Explorer從網路伺服器上讀取VBD檔,因此,在偵錯階段,我們把兩個經過編譯的使用者文件放在Visual Basic目錄中,程式完成後則把VBD檔放在網路上的伺服器。

我們在程式中使用了 #If...Then...#Else等編譯指令,告訴Visual Basic編譯器如何因應不同的環境需求來進行編譯工作。以下的程式告訴udCalc文件如何對它內含的控制項進行初值化,如何設定gchdScholar的屬性內容,以及如何載入udResult文件到Internet Explorer裡。


 

 圖9-6 應用使用者文件的Internet應用程式
Option Explicit
#Const DEBUG_MODE = True

Private Sub UserDocument_Initialize()
    `Initialize list boxes
    cmbCollege.AddItem "In-state public college", chdState
    cmbCollege.AddItem "Out-of-state public college", _
        chdOutOfState
    cmbCollege.AddItem "Private college", chdPrivate
    cmbTransport.AddItem "Bike", chdBike
    cmbTransport.AddItem "Bus", chdBus
    cmbTransport.AddItem "Used car", chdUsedCar
    cmbTransport.AddItem "New car", chdNewCar
    cmbHousing.AddItem "Home", chdHome
    cmbHousing.AddItem "Dormitory", chdDorm
    cmbHousing.AddItem "Apartment", chdApartment
    cmbCollege.ListIndex = 0
    cmbTransport.ListIndex = 0
    cmbHousing.ListIndex = 0
End Sub

`Display Costs Web page
Private Sub cmdCalculate_Click()
    `Check for valid data
    If Len(txtName) = 0 Or Len(txtAge) = 0 Then
        MsgBox "Name and age are required."
        Exit Sub
    End If
    `Set Child properties
    gchdScholar.Age = txtAge
    gchdScholar.Name = txtName
    gchdScholar.Transport = cmbTransport.ListIndex
    gchdScholar.Housing = cmbHousing.ListIndex
    gchdScholar.College = cmbCollege.ListIndex

    `Navigating differs in debug and release versions
    #If DEBUG_MODE Then
        `Use local address during debugging
        Hyperlink.NavigateTo "C:\Program Files\" & _
            "Microsoft Visual Studio\VB98\udResult.VBD"
    #Else
        `Use network address at release
        Hyperlink.NavigateTo "http:\\6.6.6.6\" & _
            "vb6dev\chap09\AXFShock\udResult.VBD"
    #End If
End Sub

HyperLink物件是內建於每一份使用者文件中的物件,你可以用HyperLink物件去巡覽不同的URL,也可以用HyperLink物件從快取記憶區中讀取前頁或後頁資料。NavigateTo方法則大約相當於表單的Show方法。

以ActiveX文件顯示計算的結果
 

當Internet Explorer第一次打開udResult文件時,Initialize事件便會被驅動。我們在udResult的Initialize事件程序中,把小孩的名字放在一個標籤上。Initialize事件程序只會在Internet Explorer啟動時被執行一次。

Initialize事件程序結束後,Show事件便會被驅動。Show事件程序告訴gchdScholar物件去計算小孩唸大學的成本,然後把計算的結果放在標籤上顯示出來。每當使用者要求顯示udResult文件時,這個Show事件程序就會被啟動。以下就是udResult文件的UserDocument_Initialize、UserDocument_Show和cmdBack_Click事件程序的內容:

Option Explicit

`Use the Initialize event to initialize information 
`that will stay the same throughout session
Private Sub UserDocument_Initialize()
    `Fill in name in label
    lblPaymentDesc = Left(lblPaymentDesc, _
        InStr(1, lblPaymentDesc, "?") - 1) & _
        gchdScholar.Name & _
        Right(lblPaymentDesc, _
        Len(lblPaymentDesc) - _
        InStr(1, lblPaymentDesc, "?"))
End Sub

`Use the Show event to update information when the
`user revisits this page
Private Sub UserDocument_Show()
    Dim LumpSum, Payment, TotalCost
    `Calculate college costs
    gchdScholar.CollegeCost Payment, LumpSum, TotalCost
    `Display costs
    lblLumpSum = LumpSum
    lblPayment = Payment
    lblTotalCost = TotalCost
End Sub

`Navigate back to the data entry page
Private Sub cmdBack_Click()
    Hyperlink.GoBack
End Sub

事實上,在Initialize事件程序中的所有動作本來都應該放在Show事件程序中,範例中的作法只是用來說明Initialize和Show事件的差異。如果你在udResult文件上按下了Back按鈕,輸入第二個孩子的資料,再按下Calculate,你會發現計算的結果變了,但是孩子的名字沒有改變。這個故意設計的程式錯誤告訴你一件事:你應該把固定不變的資料放在Initialize事件程序中,把每次都會經過計算的資料放在Show事件程序裡。

完整的Child物件類別模組(CHILD.CLS)、Costs物件類別模組(COSTS.CLS)和Invest物件類別模組(INVEST.CLS)都收錄在隨書光碟中。


參考資料:

請參閱下一節 "如何透過Internet安裝ActiveX文件? " ,在這一節中我們將要討論如何在網路上安裝Internet應用程式。


如何透過Internet安裝ActiveX文件?
 

在IE中顯示ActiveX文件之前,ActiveX文件必須先經過安裝和登錄。在未經安裝和登錄前,你不能直接開啟網路上的ActiveX文件(VBD檔),如果這麼做,Internet Explorer會以為你要把VBD檔下載到你的磁碟中,然後顯示如圖9-7中的對話方塊。如果這時你選「開啟」,這個檔案會被複製下來,同時系統會問你要用哪一個應用程式來開啟它。


 

 圖9-7 開啟網路上的VBD檔,IE會假定你要下載這個VBD檔

要產生安裝ActiveX文件的相關檔案,你可以用「封裝暨部署精靈」。使用「封裝暨部署精靈」產生ActiveX文件的安裝程式時,請按照以下這幾個步驟:

  1. 從Windows 95的「開始」功能表中找到「Microsoft Visual Basic 6.0」程式群組,打開「Microsoft Visual Basic 6.0工具」,選擇「封裝暨部署精靈」。
  2. 點選「瀏覽」按鈕,選取你的ActiveX文件專案檔,按下「封裝」按鈕。「封裝暨部署精靈」會先檢查專案中所有檔案。如果來源檔比編譯檔還新(時間較晚),輔助精靈會問你是否要重新編譯這個應用程式。接下來精靈會叫出另一個對話方塊,讓你一步一步完成工作。
  3. 選擇「Internet封裝」作為封裝類型,按下「下一步」。
  4. 在「封裝資料夾」一欄中,選擇Internet伺服器的根目錄。或者,你可以選擇任一個目錄,事後再將目錄移到Internet伺服器的目錄裡。按下「下一步」後,精靈會讓你選擇要包含的檔案。
  5. 在這裡你可以點選「加入」按鈕,加入一些其他的檔案,例如一些資料檔。完成後按下「下一步」,精靈會詢問檔案的來源。
  6. 「檔案來源」對話方塊讓你可以從Microsoft的伺服器取得Visual Basic的Runtime檔以及相關的散佈檔。如果應用程式是在企業內網路中執行,你可能要選擇「從其他網站下載」,這樣Visual Basic Runtime和OLE Automation檔才能從目前的伺服器中複製到網站中的另一個地方。如果應用程式要由Internet散佈,你可能要選「從Microsoft網站下載」,以便讓使用者取得最新版的檔案。按下「下一步」後,「安全性設定」對話方塊就會出現。
  7. 「安全性設定」對話方塊讓你可以指出哪些元件可以在Script中安全地使用,以及是否可以安全地初始化。對於Future Shock應用程式裡的每一個元件,兩項問題你都要回答"是"。按下「下一步」後,「完成」對話方塊就會出現。
  8. 在「完成」對話方塊中填入腳本名稱,按下「完成」按鈕後,精靈就會開始產生一些安裝和啟動所需的檔案。

「封裝暨部署精靈」會根據你的選項來決定產生以下各種可能的檔案,在這些檔案中,你要把前面三種複製到你的網站上。

檔案種類 概述
CAB 這種檔案包含經過壓縮的應用程式可執行檔以及相依檔案。
HTM 這種網頁檔會自動安裝從CAB檔裡經解壓縮後得到的檔案,然後會在瀏覽器中打開VBD檔。
VBD 這是經編譯後的使用者文件。
DDF 這是「封裝暨部署精靈」用來產生CAB檔的專案檔。
INF 這個檔案存放著應用程式的安裝資訊。
BAT 用來從命令列中重建應用程式所需用到的批次檔,不用圖形介面

當你複製了安裝程式相關的檔案(CAB、HTM和VBD)到網站伺服器上之後,使用者就可以藉由開啟HTM檔來執行你的應用程式了。HTM檔會在使用者的電腦上安裝和註冊可執行的元件,然後在Internet Explorer上開啟第一個ActiveX文件。

你可能需要把自動產生的HTM檔修改一下,以便讓使用者進到這個網頁就能看到你的第一份ActiveX文件。以下這段HTML碼是修改後的HTM檔,修改的部分我們以粗體字標出:

<HTML>
<HEAD>
<TITLE>AXFShock.CAB</TITLE>
</HEAD>
<BODY>
<OBJECT ID="Child"
CLASSID="CLSID:8EC98958-03B9-11D2-8E90-000000000000"
CODEBASE="AXFShock.CAB#version=1,0,0,0">
</OBJECT>
<OBJECT ID="Costs"
CLASSID="CLSID:8EC9895D-03B9-11D2-8E90-000000000000"
CODEBASE="AXFShock.CAB#version=1,0,0,0">
</OBJECT>

<OBJECT ID="Investment"
CLASSID="CLSID:8EC9895F-03B9-11D2-8E90-000000000000"
CODEBASE="AXFShock.CAB#version=1,0,0,0">
</OBJECT>
<a href=udCalc.VBD>udCalc.VBD</a>
<a href=udResult.VBD>udResult.VBD</a>

<SCRIPT LANGUAGE="VBScript">
Sub Window_OnLoad
    Document.Navigate "udCalc.VBD"
End Sub

</SCRIPT>
</BODY>
</HTML>

在Future Shock應用程式中所使用的每一個元件都有物件類別識別碼(Class ID),這些識別碼對應到HTM檔案裡就是你看到的 <CLASSID>。每次編譯應用程式時,Visual Basic都會產生新的物件類別碼,因此,每次重新編譯應用程式,你都必須重新再執行一次「封裝暨部署精靈」。

一旦建立了安裝程式的相關檔案,並且把HTM、CAB和VBD放在網站伺服器上之後,你可以用以下這兩個步驟來執行應用程式:

  1. 在IE的「位址」欄中打入應用程式HTM檔的URL。IE會檢查這個應用程式所需用到的ActiveX元件是否已經在你的機器上註冊了,如果沒有,IE會從CAB檔中解壓縮並且安裝所需的元件。
  2. 依照你的IE的安全設定和「封裝暨部署精靈」收集得來的安全性資料,IE可能會在每一個元件被安裝之前都提出警告。如果你每一次都回答「確定」,那麼IE便會完成安裝並且開啟第一份文件。

如何在Internet上安裝DHTML應用程式?
 

和ActiveX文件一樣,DHTML應用程式在放到Internet上面之前也必須加以封裝。前一節所談到安裝ActiveX文件的步驟也適用於DHTML應用程式的安裝。

「封裝暨部署精靈」在處理DHTML應用程式時有一點些微的不同,主要是其所產生的HTM檔會被修改。精靈把HTM檔的前幾行加以修改,變成使用精靈產生的CAB檔,這樣才能讓使用者開啟HTM檔時就能安裝適當的可執行檔。

你自己不用去修改精靈產生的HTM檔,這一點和ActiveX文件的安裝不同。

如何在Internet上面運用IIS應用程式?
 

IIS應用程式的可執行元件存放在Internet伺服器上,因此,不需要做任何特殊的安裝工作,只要把編譯後的應用程式放到Internet伺服器上即可。

編譯後的IIS應用程式包含ASP檔、Global.ASA檔、DLL或EXE檔以及HTM檔。可執行檔(EXE和DLL)不應該被放在公用目錄中,因為它們只在伺服器上執行。