當我們編寫程序時,會常常遇到程序信息內容更新的問題,對于小的文件更新,可以提供給客戶自己到網絡上下載,但對于大且多的文件,由于網絡的原因,通過下載卻又不實際,動輒是更新不完整,影響了程序的運行。當時我編寫“商務娛樂頻道系統”時,也遇到了這樣的問題,對于大型的視頻及圖片文件,我考慮到了使用壓縮包提供給客戶,但是通過使用壓縮程序卻不能將我的文件按要求進行解壓到其他相應的目錄,那時我想到了何不自己制作壓縮與解壓縮程序呢。解壓時將文件解壓到程序所要的位置。
為了這個項目,我仔細的研究了vb的安裝程序,原來vb是通過系統所自帶的資源來進行壓縮與解壓縮,如makecab.exe、vb6stkit.dll等。
其實真真做起來還是挺簡單的,就是調用幾個api函數便可以搞定。近日,閑著有空,翻看自己的舊程序,故決定將該程序整理出來,與大家共享。
 
下面是具體的程序編寫模塊,首先你需要建立一個工程(名稱由你自己確定了):
1. 添加兩個模塊,在這里我給它們分別命名為modapi、modmain;
2. 添加三個窗體,在這里我給它們分別命名為frmmain、frmlogin、frmaddinfo;
3. 以下是各個模塊的源代碼內容,請先保存該工程,并且關閉,然后轉到該工程的文件夾下,按下面的提示進行源代碼拷貝;
 
用記事本打開frmmain.frm文件,copy以下內容到其中:
 
version 5.00
object = "{831fdd16-0c5c-11d2-a9fc-0000f8754da1}#2.0#0"; "mscomctl.ocx"
object = "{f9043c88-f6f2-101a-a3c9-08002b2f49fb}#1.2#0"; "comdlg32.ocx"
begin vb.form frmmain 
 borderstyle = 1 'fixed single
 caption = "信息文件更新"
 clientheight = 5385
 clientleft = 45
 clienttop = 330
 clientwidth = 8550
 controlbox = 0 'false
 icon = "frmmain.frx":0000
 linktopic = "form1"
 lockcontrols = -1 'true
 maxbutton = 0 'false
 minbutton = 0 'false
 scaleheight = 5385
 scalewidth = 8550
 startupposition = 2 '屏幕中心
 begin vb.commandbutton cmdok 
 caption = "導出更新列表"
 height = 375
 index = 3
 left = 5385
 tabindex = 6
 top = 4980
 width = 1545
 end
 begin vb.commandbutton cmdok 
 caption = "關 閉"
 height = 375
 index = 2
 left = 7620
 tabindex = 5
 top = 4980
 width = 885
 end
 begin vb.commandbutton cmdok 
 caption = "打 包"
 height = 375
 index = 1
 left = 3810
 tabindex = 1
 top = 4980
 width = 885
 end
 begin vb.commandbutton cmdok 
 caption = "展 開"
 height = 375
 index = 0
 left = 0
 tabindex = 0
 top = 4980
 width = 885
 end
 begin mscomctllib.listview lstinfo 
 height = 4275
 left = 0
 tabindex = 2
 top = 330
 width = 8505
 _extentx = 15002
 _extenty = 7541
 view = 3
 arrange = 1
 labeledit = 1
 multiselect = -1 'true
 labelwrap = -1 'true
 hideselection = 0 'false
  fullrowselect = -1 'true
 gridlines = -1 'true
 _version = 393217
 forecolor = -2147483640
 backcolor = -2147483643
 borderstyle = 1
 appearance = 1
 numitems = 3
 beginproperty columnheader(1) {bdd1f052-858b-11d1-b16a-00c0f0283628} 
 text = "序號"
 object.width = 1235
 endproperty
 beginproperty columnheader(2) {bdd1f052-858b-11d1-b16a-00c0f0283628} 
 subitemindex = 1
 text = "壓縮包文件"
 object.width = 6068
 endproperty
 beginproperty columnheader(3) {bdd1f052-858b-11d1-b16a-00c0f0283628} 
 subitemindex = 2
 text = "目標信息"
 object.width = 7832
 endproperty
 end
 begin mscomdlg.commondialog comdinfo 
 left = 0
 top = 360
 _extentx = 847
 _extenty = 847
 _version = 393216
 cancelerror = -1 'true
 maxfilesize = 30000
 end
 begin mscomctllib.progressbar pgbar 
 height = 345
 left = 30
 tabindex = 4
 top = 4620
 width = 8505
 _extentx = 15002
 _extenty = 609
 _version = 393216
 appearance = 0
 scrolling = 1
 end
 begin vb.label lblabout 
 backstyle = 0 'transparent
 caption = "關于本程序..."
 height = 255
 left = 7260
 tabindex = 8
 top = 60
 width = 1215
 end
 begin vb.label lblinfo 
 autosize = -1 'true
 caption = "請等待,正在創建包信息文件..."
 height = 180
 index = 1
 left = 30
 tabindex = 7
 top = 4740
 width = 4980
 end
 begin vb.label lblinfo 
 autosize = -1 'true
 caption = "展開打包信息更新列表:"
 height = 180
 index = 0
 left = 30
 tabindex = 3
 top = 30
 width = 1980
 end
end
attribute vb_name = "frmmain"
attribute vb_globalnamespace = false
attribute vb_creatable = false
attribute vb_predeclaredid = true
attribute vb_exposed = false
 
 
' ==============================================
' 信息打包與展開 (主窗體模塊,即展開窗體)
'
' 功能 :利用系統所存在的資源自作壓縮與解壓縮程序
'
' 作 者 :謝家峰
' 整理日期 :2004-08-08
' email :[email protected]
'
' ==============================================
'
 
option explicit
 
private declare function extractfilefromcab lib "vb6stkit.dll" _
 (byval cab as string, byval file as string, byval dest as string, _
 byval icab as long, byval ssrc as string) as long
'說明:
'cab 為系統安裝目錄下的壓縮包
'file 為壓縮包內的某文件名稱(需在該文件名前加“@”字符)
'dest 為壓縮包內的某文件解壓后的完全路徑名
'icab 為壓縮包的數目
'ssrc 臨時文件夾,一個有效的文件夾路徑
 
dim s_filenames() as string '源文件名(不含路徑)
dim d_filenames() as string '目標文件名(含路徑)
dim cab_filename as string '包文件名
 
 
private sub cmdok_click(index as integer)
 dim filenum as long
 dim i as long
 dim j as long
 dim filename as string
 
 select case index
 case 0
  filename = app.path & "/更新.ini"
 '查找包文件信息
 s_filenames = getfiles(app.path & "/*.cab_")
 if ubound(s_filenames) = 0 then
 msgbox "當前目錄下沒找到“商務頻道系統文件更新”包文件!", , app.exename
 exit sub
 end if
 
 if ubound(s_filenames) > 1 then
 with comdinfo
 .filter = "商務頻道系統文件更新包|*.cab_|"
 .dialogtitle = "請指定“商務頻道系統文件更新”包的位置"
 .initdir = app.path
 .flags = cdlofnfilemustexist or cdlofnhidereadonly
 .filename = app.path & "/" & s_filenames(1)
 on error goto errfind
 .showopen
 
 cab_filename = trim(right(.filename, len(.filename) - len(app.path & "/")))
 on error goto 0
 end with
 else
 cab_filename = s_filenames(1)
 end if
 
 screen.mousepointer = 11
 pgbar.visible = false
 lblinfo(1).visible = true
 doevents
 
 '將當前包復制到系統安裝文件夾下
 if fileexists(windowspath & cab_filename) then kill windowspath & cab_filename
 filecopy app.path & "/" & cab_filename, windowspath & cab_filename
 '轉換包路徑信息(為系統安裝目錄下的文件)
 cab_filename = windowspath & cab_filename
 setattr cab_filename, vbnormal
 
 '獲得“更新.ini”文件
 j = extractfilefromcab(cab_filename, "@更新.ini", filename, 1, app.path & "/")
 setattr filename, vbnormal
 
 lblinfo(1).visible = false
 pgbar.visible = true
 screen.mousepointer = 1
 doevents
 
 if j = 0 then
 msgbox "該壓縮包信息不完整,或不是“商務頻道系統文件更新”包!" & vbcrlf & vbcrlf & "解壓沒完成,請索取最新的更新包!", , app.exename
 '刪除系統安裝目錄下的復制包
 kill cab_filename
 exit sub
 else
 setattr filename, vbnormal
 end if
 
 screen.mousepointer = 11
 '解壓信息
 filenum = clng(clng(readinifile(filename, "文件數目", "filenum")))
 redim s_filenames(filenum)
 redim d_filenames(filenum)
 '其中s_filenames的最后一個數據為播放信息文件
 for i = 1 to filenum
 s_filenames(i - 1) = readinifile(filename, "源文件信息", "file" & i)
 s_filenames(i - 1) = getfilename(s_filenames(i - 1))
 d_filenames(i - 1) = readinifile(filename, "目標文件信息", "file" & i)
 doevents
 next
 
 lstinfo.listitems.clear
 pgbar.min = 1
 pgbar.max = filenum + 1
 
 for i = 1 to filenum
 doevents
 '建立文件夾
 createfloder d_filenames(i - 1)
 '解壓文件
 if fileexists(d_filenames(i - 1)) then setattr d_filenames(i - 1), vbnormal
 j = extractfilefromcab(cab_filename, "@" & s_filenames(i - 1), d_filenames(i - 1), 1, app.path & "/")
 if j = 0 then
 msgbox "該壓縮包信息不完整,或不是“商務頻道系統文件更新”包!" & vbcrlf & vbcrlf & "解壓沒完成,請索取最新的更新包!", , app.exename
 lstinfo.listitems.clear
 pgbar.min = 0
 pgbar.value = 0
 screen.mousepointer = 1
 exit sub
 end if
 pgbar.value = i
 doevents
 lstvinfo_add lstinfo, 3, false, lstinfo.listitems.count + 1, s_filenames(i - 1), d_filenames(i - 1)
 next
 
 '刪除系統安裝目錄下的復制包
 kill cab_filename
 kill filename
 pgbar.value = filenum + 1
 
 msgbox "解壓縮完成,系統更新完成,謝謝使用!", , app.exename
 pgbar.min = 0
 pgbar.value = 0
 
 case 1 ' 執行信息打包
 lstinfo.listitems.clear
 frmlogin.show 1, me
 case 2
 unload me
 case 3
 if lstinfo.listitems.count = 0 then msgbox "無信息可供導出!", , app.exename: exit sub
 with frmmain.comdinfo
 .filter = "更新列表信息|*.txt"
 .dialogtitle = "導出包列表信息文件"
 .initdir = curdir()
 .flags = cdlofnhidereadonly
 .filename = "更新列表.txt"
 on error goto errlab
 .showsave
 
 filename = .filename
 if fileexists(filename) then
 setattr filename, vbnormal
 kill filename
 end if
 '導出信息
 with lstinfo
 writeprivateprofilestring "文件數目", "filenum", cstr(.listitems.count), filename
 for i = 1 to .listitems.count
 writeprivateprofilestring "壓縮包文件信息", "file" & i, .listitems(i).subitems(1), filename
 writeprivateprofilestring "目標文件信息", "file" & i, .listitems(i).subitems(2), filename
 next
 end with
 end with
 msgbox "信息列表被導出在“" & filename & "”文件中!", , app.exename
 
 case else
end select
 
screen.mousepointer = 1
exit sub
 
errlab:
 if err.number = 32755 then
 '解壓文件
 d_filenames(filenum) = app.path & "/" & s_filenames(filenum)
 if fileexists(d_filenames(i - 1)) then setattr d_filenames(filenum), vbnormal
 extractfilefromcab cab_filename, "@" & s_filenames(filenum), d_filenames(filenum), 1, app.path & "/"
 setattr d_filenames(filenum), vbnormal
 
 pgbar.value = filenum + 1
 lstvinfo_add lstinfo, 3, false, lstinfo.listitems.count + 1, s_filenames(filenum), app.path & "/" & s_filenames(filenum)
 '刪除系統安裝目錄下的復制包
 if fileexists(cab_filename) then kill cab_filename
 kill filename
 
 msgbox "您取消了指定用戶信息的位置,該用戶信息缺省被放在“" & d_filenames(filenum) & "”!" _
 & vbcrlf & vbcrlf & "解壓縮完成,系統更新完成,謝謝使用!", , app.exename
 pgbar.min = 0
 pgbar.value = 0
 else
 err.raise err.number, , err.description
 end if
 
 screen.mousepointer = 1
 exit sub
 
errfind:
 if err.number = 32755 then
 else
 err.raise err.number, , err.description
 end if
 screen.mousepointer = 1
 exit sub
end sub
 
private sub lblabout_click()
 lblabout.borderstyle = 1
 frmabout.show 1, me
end sub
 
private sub lstinfo_itemclick(byval item as mscomctllib.listitem)
 if not (item is nothing) then
 lstinfo.tooltiptext = "[目標信息] " & item.listsubitems(2)
 end if
end sub