直播中
使用 VB 5.0,我們要開(kāi)發(fā)一個(gè)ActiveX 動(dòng)態(tài)鏈接庫(kù)。這個(gè)動(dòng)態(tài)鏈接庫(kù)讓我們能夠連接到SQL數(shù)據(jù)庫(kù),提取圖片數(shù)據(jù),并把它們保存成文件,放在目錄里。要建立動(dòng)態(tài)鏈接庫(kù),請(qǐng)?jiān)诖蜷_(kāi)VB程序之后執(zhí)行下列步驟:首先:在文件(File)菜單里,選擇新建項(xiàng)目(New Project)。接著,在新建立項(xiàng)目對(duì)話框里,雙擊ActiveX DLL 圖標(biāo)。VB自動(dòng)地向項(xiàng)目里增加一個(gè)類(lèi),叫做Class1。然后,在屬性容器里,雙擊名稱(chēng)(Name)屬性,把它改成clsImageLoader,保持instancing 屬性為缺省值MultiUse不動(dòng)。最后,在項(xiàng)目(Project)菜單里,選擇Project1 屬性,打開(kāi)項(xiàng)目屬性對(duì)話框。選擇通用(General)選項(xiàng)卡,把項(xiàng)目名稱(chēng)改為ImageLoader。其它字段可以不管,保持原樣。單擊確定(OK)完成對(duì)ImageLoader 這個(gè)工程的設(shè)置。
在類(lèi)里,寫(xiě)入了5個(gè)Let屬性,1個(gè)Get屬性(只讀)和兩個(gè)方法。Let屬性傳遞動(dòng)態(tài)鏈接庫(kù)需要的信息,Get屬性提供動(dòng)態(tài)鏈接庫(kù)生成的圖片文件的位置。兩個(gè)方法用來(lái)打開(kāi)到數(shù)據(jù)庫(kù)的連接,以生成圖片文件。表 A 總結(jié)了這些屬性和方法的作用。當(dāng)然,根據(jù)項(xiàng)目的需要,可以在類(lèi)里加入更復(fù)雜的功能。
表A: 在ActiveX動(dòng)態(tài)鏈接庫(kù)里的屬性和方法
屬性/方法 作用
DbName 打開(kāi)數(shù)據(jù)庫(kù)連接所需的數(shù)據(jù)庫(kù)名稱(chēng)。
TableName,
NameOfImageColumn, 打開(kāi)記錄集所需要的信息。
NameOfImageTypeColumn,
NameOfImageIdColumn
ImageFile (只讀) 把圖片文件的名稱(chēng)和位置返回給容器。
OpenConnection (方法) 打開(kāi)數(shù)據(jù)庫(kù)連接。
CreateTemplateImageFile (方法) 從數(shù)據(jù)庫(kù)提取圖片數(shù)據(jù),并把它保存到目錄里。
在類(lèi)里還有其它的私有子程序,用來(lái)初始化類(lèi)、終止類(lèi)、打開(kāi)記錄集、建立圖片文件,以及處理可能的錯(cuò)誤。
注意微軟活動(dòng)數(shù)據(jù)對(duì)象ADO1.5(現(xiàn)在為2.0)被用來(lái)連接SQL數(shù)據(jù)庫(kù)。也可以使用其它數(shù)據(jù)訪問(wèn)方法,比如遠(yuǎn)程數(shù)據(jù)對(duì)象RDO。在這個(gè)項(xiàng)目里,必須使用ADO。操作方法是,單擊項(xiàng)目(Project)菜單,然后選擇引用(References)菜單 項(xiàng)。在引用對(duì)話框里,選中微軟ActiveX Data Objects 1.5 庫(kù),然后單擊確定(OK)。
在列表 B里,列出了類(lèi)ImageLoader 完整源代碼。類(lèi)里使用的變量定義都在代碼內(nèi)部給出,還有其它注釋?zhuān)瑤椭斫馍舷挛摹?/P>
列表 B:類(lèi) ImageLoader 的完整源代碼
Private mAdoConn As New ADODB.Connection
Private mAdoRst As New ADODB.Recordset
Private mstrDbName As String
Private mstrTableName As String
Private mstrImageColumnName As String '圖片字的名稱(chēng)。
Private mstrImageTypeColumnName As String '圖片類(lèi)型字段的名稱(chēng)。
Private mstrImageIdColumnName As String '圖片ID字段的名稱(chēng)。
Private mstrFileName() As String '數(shù)組,里面包含文件名和路徑。
Private mlngImageId() As Long '數(shù)組,里面包含圖片ID
Private mlngNumberOfFiles As Long
Const BLOCKSIZE = 102400
Public Property Let DbName(ByVal strVal As String)
mstrDbName = strVal
End Property
Public Property Let TableName(ByVal strVal As String)
mstrTableName = strVal
End Property
Public Property Let NameOfImageColumn(ByVal strVal As String)
mstrImageColumnName = strVal
End Property
Public Property Let NameOfImageTypeColumn(ByVal strVal As String)
mstrImageTypeColumnName = strVal
End Property
Public Property Let NameOfImageIdColumn(ByVal strVal As String)
mstrImageIdColumnName = strVal
End Property
Public Property Get ImageFile(ByVal ImageId As Integer) As String
Dim intPos As Integer
Dim blnFindId As Boolean
Dim i As Integer
blnFindId = False
For i = 0 To mlngNumberOfFiles - 1
If mlngImageId(i) = ImageId Then
intPos = 5 + Len(ImageId) + 3
ImageFile = Right(mstrFileName(i), intPos) 'reformat the location of file.
blnFindId = True
End If
Next i
If blnFindId = False Then
Err.Clear
Err.Raise vbObjectError + 23, "Get ImageFile", "Can't find image file!"
End If
End Property
Public Sub OpenConnection()
'**********************************************************
'作用:打開(kāi)數(shù)據(jù)庫(kù)連接。
'**********************************************************
On Error GoTo Error_handler
If mstrDbName = "" Then GoTo Error_handler
If mAdoConn.State = adStateOpen Then mAdoConn.Close
mAdoConn.ConnectionString = "DRIVER={SQL Server};SERVER=(local);UID=sa;PWD=;WSID=JIA;DATABASE=" & mstrDbName
mAdoConn.ConnectionTimeout = 15
mAdoConn.Open
Exit Sub
Error_handler:
Call HandleError
End Sub
Public Sub CreateTempImageFile(ByVal ImageId As Integer)
Dim strImageType As String
Dim i As Integer
'**********************************************************
'作用:打開(kāi)記錄集,提取二進(jìn)制數(shù)據(jù),并把數(shù)據(jù)存入文件。注意文件名使用圖片ID生成。
'輸入:圖片ID。
'**********************************************************
If mAdoConn.State = adStateClosed Then Exit Sub
Call OpenRecordset(ImageId)
If mAdoRst.State = adStateClosed Then Exit Sub
On Error GoTo Error_handler
For i = 0 To mlngNumberOfFiles - 1
'檢測(cè)圖片文件是否已經(jīng)存在。
If mlngImageId(i) = ImageId Then Exit Sub
Next i
mlngNumberOfFiles = mlngNumberOfFiles + 1
ReDim Preserve mstrFileName(mlngNumberOfFiles) '改變數(shù)組大小。
ReDim Preserve mlngImageId(mlngNumberOfFiles) '改變數(shù)組大小。
mlngImageId(mlngNumberOfFiles - 1) = ImageId
strImageType = mAdoRst.Fields(mstrImageTypeColumnName) ' 取得圖片類(lèi)型。
mstrFileName(mlngNumberOfFiles - 1) = App.Path & "\images" & _
"\image" & LTrim(Str(ImageId)) & "." & strImageType '取得圖片文件名稱(chēng)和位置。
Call ReadFromDB(mAdoRst.Fields(mstrImageColumnName), _
mstrFileName(mlngNumberOfFiles - 1), AdoRst.Fields(mstrImageColumnName).ActualSize)
Exit Sub
Error_handler:
Call HandleError
End Sub
Private Sub OpenRecordset(ByVal ImageId As Integer)
Dim SqlText As String
'**********************************************************
'作用:打開(kāi)記錄集。
'輸入:圖片ID。
'**********************************************************
On Error GoTo Error_handler
If mAdoRst.State = adStateOpen Then mAdoRst.Close
SqlText = "SELECT " & mstrImageColumnName & "," & _
mstrImageTypeColumnName & " FROM " & mstrTableName & _
" WHERE " & mstrImageIdColumnName & "=" & ImageId
Set mAdoRst.ActiveConnection = mAdoConn
mAdoRst.Open SqlText, , adOpenStatic, adLockReadOnly 'Open recordset.
Exit Sub
Error_handler:
Call HandleError
End Sub
Private Sub ReadFromDB(fld As ADODB.Field, ByVal DiskFile As String, _
FldSize As Long)
Dim NumBlocks As Integer
Dim LeftOver As Long
Dim byteData() As Byte '字節(jié)數(shù)組,用于長(zhǎng)的可變二進(jìn)制數(shù)據(jù)LongVarBinary。
Dim strData As String '字符串,用于長(zhǎng)的可變二進(jìn)制數(shù)據(jù)LongVarChar。
Dim DestFileNum As Integer
Dim pic As Variant
Dim i As Integer
'**********************************************************
'作用:提取二進(jìn)制數(shù)據(jù)并把數(shù)據(jù)放入文件。
'輸入:圖片字段,文件名/位置和數(shù)據(jù)尺寸。
'**********************************************************
If Len(Dir(DiskFile)) > 0 Then '刪除已經(jīng)存在的目標(biāo)文件。
Kill DiskFile
End If
DestFileNum = FreeFile
Open DiskFile For Binary As DestFileNum
NumBlocks = FldSize \ BLOCKSIZE
LeftOver = FldSize Mod BLOCKSIZE
Select Case fld.Type
Case adLongVarBinary '用于圖片數(shù)據(jù)類(lèi)型。
byteData() = fld.GetChunk(LeftOver)
pic = fld.GetChunk(LeftOver)
Put DestFileNum, , byteData()
For i = 1 To NumBlocks
byteData() = fld.GetChunk(BLOCKSIZE)
Put DestFileNum, , byteData()
Next i
Case adLongVarChar '用于文本數(shù)據(jù)類(lèi)型。
For i = 1 To NumBlocks
strData = String(BLOCKSIZE, 32)
strData = fld.GetChunk(BLOCKSIZE)
Put DestFileNum, , strData
Next i
strData = String(LeftOver, 32)
strData = fld.GetChunk(LeftOver)
Put DestFileNum, , strData
Case Else
Err.Clear
Err.Raise vbObjectError + 22, "Read from DB", "Not a Chunk Required column!"
End Select
Close DestFileNum
End Sub
Private Sub HandleError()
Dim adoErrs As ADODB.Errors
Dim errLoop As ADODB.Error
Dim strError As String
Dim i As Integer
'**********************************************************
'作用:處理可能的錯(cuò)誤。
'**********************************************************
If mAdoConn.State = adStateClosed Then GoTo Done
i = 1
Set adoErrs = mAdoConn.Errors
For Each errLoop In adoErrs '枚舉錯(cuò)誤集。
With errLoop
strError = strError & vbCrLf & " ADO Error #" & .Number
strError = strError & vbCrLf & " Description " & .Description
strError = strError & vbCrLf & " Source " & .Source
i = i + 1
End With
Next
Done:
Err.Raise vbObjectError + 21, "", strError
End Sub
Private Sub Class_Initialize()
mlngNumberOfFiles = 0
End Sub
Private Sub Class_Terminate()
Dim i As Integer
On Error GoTo Error_handler
If mAdoRst.State = adStateOpen Then mAdoRst.Close '關(guān)閉記錄集。
If mAdoConn.State = adStateOpen Then mAdoConn.Close '關(guān)閉連接。
Set mAdoRst = Nothing
Set mAdoConn = Nothing
Exit Sub
Error_handler:
Call HandleError
End Sub
Error_handler:
Call HandleError
End Sub
下一步是編譯動(dòng)態(tài)鏈接庫(kù)。在文件(File)菜單里,單擊建立(Make) ImageLoader.dll。VB會(huì)詢(xún)問(wèn)保存動(dòng)態(tài)鏈接庫(kù)的位置,然后就編譯項(xiàng)目。在要ASP文件里使用ImageLoader.dll這個(gè)動(dòng)態(tài)鏈接庫(kù),必須在Windows注冊(cè)表里注冊(cè)它。操作方法是,在NT的啟動(dòng)菜單里,選擇運(yùn)行(Run),然后在輸入框里輸入下面的命令行:
regsvr32 localpath\ImageLoader
注意,實(shí)際使用時(shí)要用動(dòng)態(tài)鏈接庫(kù)實(shí)際所在的完整路徑替換上面命令行里的“l(fā)ocalpath”?,F(xiàn)在,就可以在程序里,比如ASP文件里使用這個(gè)動(dòng)態(tài)鏈接庫(kù)了。