ListView控件比前面幾種控件要復(fù)雜一些,通過此控件,,可將項目組成帶有或不帶有列標(biāo)頭的列,并顯示伴隨的圖標(biāo)和文本,。ListView控件是由ColumnHeader和ListItem對象所組成的,,其中ColumnHeader對象的個數(shù)決定了控件的列數(shù),而ListItem對象的個數(shù)則決定了控件的行數(shù),。(圖7)
ColumnHeader對象是ListView控件中包含標(biāo)頭文字的項目,。利用ColumnHeader對象,用戶可以:
▲單擊對象觸發(fā)ColumnClick事件并根據(jù)數(shù)據(jù)項目將項目排序,。
▲拖動對象的右邊框來調(diào)整列寬度,。
▲在報表視圖中隱藏ColumnHeader對象。
ColumnHeader對象的數(shù)目決定每個ListItem對象可包含的子項目數(shù)目,。刪除ColumnHeader對象后所有與列關(guān)聯(lián)的子項目也將被刪除,,并且每個ListItem對象的子項目數(shù)組將平移以更新ColumnHeader的索引,而這將導(dǎo)致剩余的列標(biāo)頭SubItemIndex屬性的改變,。
ColumnHeader對象的SubItemIndex屬性
該屬性返回與ListView控件中ColumnHeader對象關(guān)聯(lián)的子項目的索引,。子項目是字符串?dāng)?shù)組,代表顯示在報表視圖中的ListItem對象的數(shù)據(jù),。第一列的列標(biāo)頭SubItemIndex屬性設(shè)置為0,,這是因為小圖標(biāo)和ListItem對象的文字總出現(xiàn)在第一列中,而且它們被當(dāng)作ListItem對象而不是子項目,。列標(biāo)頭數(shù)目取決于子項目數(shù)目,。列標(biāo)頭數(shù)目總是比子項目數(shù)目多1。
在設(shè)計時可以利用屬性頁的“列首”選項卡將ColumnHeader對象添加到ListView控件中,,在運行時則用Add方法添加,。
ColumnHeader對象的Add方法
該方法的使用與前面那些控件基本相似,,就不再介紹了,。
ListView1.ColumnHeader.Add(index,key,text,width,alignment)
ListItem對象是指控件中的一行(不包含標(biāo)頭行)的所有內(nèi)容,。它也可包含文本和圖片,但是要使用圖片則必須通過Icons和SmallIcons屬性引用ImageList控件,。
ListItem對象的SubItems屬性
返回或設(shè)置一個字符串(子項目)數(shù)組,,它代表ListView控件中ListItem對象的數(shù)據(jù)。
ListItem對象可包含任意多個的關(guān)聯(lián)項目數(shù)據(jù)字符串(子項目),,但每個ListItem對象子項目數(shù)目必須相同,。每個子項目都對應(yīng)于相關(guān)的列標(biāo)頭,無法直接向子項目數(shù)組添加元素,,只有通過ColumnHeaders的Add方法添加列標(biāo)頭的方法來添加子項目,。
ListItem對象的Add方法
該方法添加ListItem對象到ListView控件的ListItems集合中并返回對新創(chuàng)建對象的引用。
它的語法如下:
ListItem1.Add(index,key,text,icon,smallIcon)
ListView控件的View屬性
ListView控件可使用四種不同視圖顯示項目,,這可以用View屬性來確定,。該屬性返回或設(shè)置ListView控件中ListItem對象的外觀。
ListView控件的SortOrder,,SortKey和Sorted屬性
控件中的ListItem對象可以按要求進行排序,,與排序有關(guān)的屬性是SortOrder,Sorted和SortKey屬性,。
SortOrder屬性返回或設(shè)置一個值,,此值決定ListView控件中的ListItem對象以升序或降序排序。
SortKey屬性返回或設(shè)置一個值,,此值決定ListView控件中的ListItem對象如何排序,。
Sorted屬性返回或設(shè)置確定ListView控件中的ListItem對象是否排序的值。
下面的代碼說明了如何創(chuàng)建ColumnHeaders和ListItem對象,,SubItemIndex和SubItem屬性的使用方法以及如何排序,。
Private Sub Form_load()
'確保ListView控件的view屬性為報表視圖。
ListView1.View=lvwReport
'添加三列,。
ListView1.ColumnHeaders.Add,"Name","姓名"
ListView1.ColumnHeaders.Add,"Sex","性別"
ListView1.ColumnHeaders.Add,"Age","年齡"
'向控件添加ListItem對象,。
Dim itmX As ListItem
'添加column1的名稱。
Set itmX=ListView1.ListItems.Add(1,"ZL","張力")
'使用SubItemIndex將SubItem與正確的ColumnHeader關(guān)聯(lián),。使用關(guān)鍵字("Sex")指定正確的ColumnHeader,。
itmX.SubItems(ListView1.ColumnHeaders("Sex").SubItemIndex)="男"
'使用ColumnHeader關(guān)鍵字將SubItems字符串與
'正確的ColumnHeader關(guān)聯(lián)。
itmX.SubItems(ListView1.ColumnHeaders("Age").SubItemIndex)="19"
Set itmX=ListView1.ListItems.Add(1,"LF","李芳")
itmX.SubItems(ListView1.ColumnHeaders("Sex").SubItemIndex)="男"
itmX.SubItems(ListView1.ColumnHeaders("Age").SubItemIndex)="22"
Set itmX=ListView1.ListItems.Add(1,"WW","王偉")
itmX.SubItems(ListView1.ColumnHeaders("Sex").SubItemIndex)="男"
itmX.SubItems(ListView1.ColumnHeaders("Age").SubItemIndex)="24"
End Sub
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As ComctlLib.ColumnHeader)
Select Case ColumnHeader.Key
Case "Sex":ListView1.SortKey=1
ListView1.SortOrder=lvwAscending
ListView1.Sorted=True
Case "Age":ListView1.SortKey=2
ListView1.SortOrder=lvwAscending
ListView1.Sorted=True
End Select
End Sub
一,、ListView使用簡介
ListView控件是VB開發(fā)者非常喜愛的控件之一,。作為Windows95公共控件組(COMCTL32.OCX)的成員,它經(jīng)常與經(jīng)常與TreeView、ImageList等控件聯(lián)合使用,。即用TreeView顯示一個的樹型結(jié)構(gòu),,而用ListView顯示選中的節(jié)點(Node)對 象的記錄集,。
這是筆者在開發(fā)財務(wù)軟件項目中的<<憑證管理>> 模塊的一個用戶界面。屏幕左邊是一個TreeView控件,,用來顯示會計憑證的類別,;右邊是一個ListView,用來顯示對應(yīng)類別的憑證目錄,;上方是一個菜單條控件(MenuBar)和一個工具條控件(ToolBar),;下方是一個狀態(tài)欄控件(StatusBar),用來顯示憑證數(shù)個當(dāng)前日期,。
大家可以看到圖中所示的界面非常類似于Window95/98 的資源瀏覽器,Windows的界面風(fēng)格做為一種標(biāo)準(zhǔn)已為廣大用戶所接受,。而Windows操作系統(tǒng)的主要的優(yōu)點就是為所有的應(yīng)用程序提供了公用的界面。知道如何使用基于Windows的應(yīng)用程序的用戶,,很容易學(xué)會使用其他應(yīng)用程序,。
這種使用Windows95公共控件組合的方法能夠達到與Windows界面的一致性,所以在目前VB5.0應(yīng)用程序的開發(fā)中經(jīng)常使用,。
二,、填充大量結(jié)果集所遇到的問題
在實際應(yīng)用開發(fā)中,經(jīng)常用ListView填充一個數(shù)據(jù)庫 結(jié)果集(Record set)的內(nèi)容,。即先寫一段SQL查詢語句,,產(chǎn)生一個結(jié)果集,然后將結(jié)果集的每一條記錄用DO...LOOP循環(huán)語句中填到ListView中,。
但是當(dāng)結(jié)果集很大時(例如有5000條以上的記錄) ,,填充所需要的時間會很長。用戶不得不等很長時間完成一個查詢,。所以在查詢的過程中必須允許用戶按Escape鍵退出,。具體做法是在DO...LOOP循環(huán)體中加一條DoEvents函數(shù),并寫一段中斷退出程序代碼,。
DoEvents函數(shù)的功能是:轉(zhuǎn)讓控制權(quán),,以便讓操作系統(tǒng)處理其它的事件。這樣在長時間的查詢過程中,,如果用戶按了Escape鍵,,將退出循環(huán) 體,結(jié)束查詢過程,。
但是這樣又會引發(fā)另外一個問題:由于DoEvents 可以讓操作系統(tǒng)響應(yīng)別的事件,,循環(huán)體中填充每一條ListView項目(ListItem)的過程也會顯示出來,所以在填充的過程中屏幕會不停的閃動,,這種現(xiàn)象當(dāng)然不能被用戶所接受,。如何 解決這個問題呢?
三,、解決方案
用WindowsAPI函數(shù)可以解決這個問題,。首先對幾個 用到的API函數(shù)做一解釋和說明,。
1.GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
此函數(shù)的功能是獲得一個指定對象窗口(Window) 的矩型框區(qū)域(rectangle)。
Hwnd為指定對象或窗體的句柄,。LpRect為返回矩 型框的結(jié)構(gòu)(必須定義為結(jié)構(gòu)類型的變量),。
2.ValidateRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
此函數(shù)的功能是使指定的矩型區(qū)域生效。這樣會 通知Windows不必對指定的區(qū)域進行重畫(Redraw),。
3.InvalidateRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT, ByVal bErase As Long) As Long
此函數(shù)的功能是使指定的矩型區(qū)域無效,。這樣會 通知Windows要對指定的區(qū)域進行重畫,。
具體實現(xiàn)的步驟如下:
1.在填充結(jié)果集之前先用GetClientRect函數(shù)獲 得ListView的顯示區(qū)域,。
2.在增加完一個顯示項目(ListItem)后用ValidateRect 函數(shù)置這一區(qū)域為有效。這樣Windows就不會顯示每一條ListItem,,屏幕閃動的現(xiàn)象就會消 失,。
3.在填充結(jié)果集之后,用InvalidateRect函數(shù)置這一區(qū)域為無效。這樣Windows就會重畫ListView的內(nèi)容,,結(jié)果集被完整的顯示出來,。
下面是筆者在項目開發(fā)中的一個程序?qū)嵗3绦蛎麨镕illListView,。該程序?qū)⑻顚懸粋€Access數(shù)據(jù)庫(FISCAL.MDB)的憑證表(Table)的內(nèi)容到ListView中,。
首先進入VB5.0,新建一個窗體(Form),,名為Form1,。
然后在Form中增加下列控件。
控 件 名 Name
ListView Lvw
Imagelist imlList
Command Button,。 Command1
將ImageList控件中充填一個名為“item”的圖象后 與ListView控件關(guān)聯(lián),。
在<<工程>>菜單命令條中進入“引用”對話框,選擇“MicrosoftDAOObjectLibrar
在Form的通用模塊(Modle)中定義以下變量。
Private Type RECT ' 用 來 定 義 一 個 區(qū) 域 的 坐 標(biāo),。
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
' - -
' Windows API 函 數(shù) 的 聲 明,。
Private Declare Function InvalidateRect Lib "user32"
(ByVal hwnd As Long, lpRect As RECT, ByVal bErase As Long) As Long
Private Declare Function ValidateRect Lib "user32"
(ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function GetClientRect Lib "user32"
(ByVal hwnd As Long, lpRect As RECT) As Long
Dim mbSearchCancel As Boolean
' 用 來 定 義 查 詢 中 斷 的 標(biāo) 志。
' True 表 示 中 止 查 詢,;False 表 示 正 在 查 詢,。
將 該Form 的KeyPreview 屬 性 設(shè) 為True, 以 控 制 窗 體 接 收 鍵 盤 事 件,。
然 后 在Form 的KeyPress 事 件 中 寫 下 列 代 碼:
If KeyAscii = vbKeyEscape Then
mbSearchCancel = True
' 當(dāng) 用 戶 按Escape 鍵 時,, 置mbSearchCancel 變 量 為True。
End If
' 表 示 結(jié) 束 查 詢,。
在Command Button 的 Click 事 件 中 調(diào) 用 填 充 子 程 序:Call FillListView,。
子 程 序 的 代 碼 為:
Private Sub FillListView()
'
Dim itmX As ListItem ' 定 義 一 個ListView 的 顯 示 項 目。
Dim sSQL As String ' 查 詢 字 串 變 量 ,。
'
Dim rc As RECT ' ListView 的 顯 示 區(qū) 域,。
Dim wrkJet As Workspace ' 數(shù) 據(jù) 庫 工 作 空 間,。
Dim dbFISCAL As Database ' 數(shù) 據(jù) 庫 對 象。
Dim RS As Recordset ' 數(shù) 據(jù) 結(jié) 果 集,。
On Error GoTo ErrFillListView
Screen.MousePointer = vbHourglass
lvw.ListItems.Clear: ' 清 除ListView 的 內(nèi) 容,。
'
' 定 義ListView 的 列 頭 的 名 稱。
With lvw.ColumnHeaders
.Add , , " 憑 證 編 號", 800
.Add , , " 憑 證 日 期", 1000
.Add , , " 憑 證 字 號", 1000
.Add , , " 憑 證 類 別", 800
.Add , , " 首 行 摘 要", 1440
.Add , , " 借 方 金 額 合 計", 1000, lvwColumnRight
End With
' - - -
' 產(chǎn) 生 查 詢 語 句,。
sSQL = "select voucher_id,voucher_number,voucher_date,voucher_type_shortname,"
sSQL=sSQL&"voucher_type_name,voucher_memo,voucher_amount from VOUCHER"
sSQL = sSQL & "order by voucher_number"
' ' - - -
' 打 開 一 個 數(shù) 據(jù) 庫 結(jié) 果 集,。
Set wrkJet = CreateWorkspace("NewJetWorkspace", "admin", "", dbUseJet)
Set dbFISCAL = wrkJet.OpenDatabase("FISCAL.mdb")
Set RS=. dbFISCAL .Open sSQL,dbOpenForwardOnly
'
' 獲 得listview 的 顯 示 區(qū) 域。
Call GetClientRect(lvw.hwnd, rc)
Do While Not RS.EOF()
DoEvents
If mbSearchCancel Then
' 中 斷 退 出
RS.Close: Set RS = Nothing ' 關(guān) 閉,、 清 除 結(jié) 果 集,。
mbSearchCancel = False
Screen.MousePointer = vbDefault
' - -
' 刷 新ListView 的 內(nèi) 容, 顯 示 已 經(jīng) 查 出 的 記 錄 數(shù),。
Call InvalidateRect(lvw.hwnd, rc, True)
Exit Sub
End If
' - - -
' 增 加 一 個 顯 示 項 目ListItem,。
With lvw.ListItems
Set itmX = .Add(, , "" & RS!voucher_number, "item", "item")
' 憑 證 編 號
itmX.SubItems(1) = Format$("" & RS!voucher_date, "yyyy/mm/dd")
' 憑 證 日 期
itmX.SubItems(2) = "" & RS!voucher_type_shortname & "-" —
' 憑 證 字 號
& "" & RS!voucher_number
itmX.SubItems(3)="" & RS!voucher_type_name
' 憑 證 類 別
itmX.SubItems(4)=""&RS!voucher_memo
' 首 行 摘 要
itmX.SubItems(5)= Format$("" & RS!voucher_amount, "#,###.00")
' 借 方 合 計 金 額
itmX.Tag = "" & RS!voucher_id
End With
' - -
' 避 免 顯 示 區(qū) 域 的 閃 動 現(xiàn) 象。
Call ValidateRect(lvw.hwnd, rc)
RS.MoveNext
Loop
'
'- 刷 新ListView 的 內(nèi) 容,。 顯 示 所 有 查 出 的 記 錄 數(shù),。
Call InvalidateRect(lvw.hwnd, rc, True)
' -
' 關(guān) 閉、 清 除 結(jié) 果 集,。
RS.Close: Set RS = Nothing
creen.MousePointer = vbDefault
Exit Sub
ErrFillListView:
Screen.MousePointer = vbDefault
MsgBox Err & ":" & Error, vbInformation, Me.Caption
Exit Sub
End Sub
編 寫 完 畢 后 按F5 執(zhí) 行 該 程 序,, 用 鼠 標(biāo) 點 擊CommandButton, 將 開 始 查 詢 并 填 寫憑 證 的 內(nèi) 容 到ListView 中 去,。
關(guān) 于ListView 本 文 只 是 描 述 了 它 如 何 填 充 大 量 結(jié) 果 集 的 方 法,, 它 還 有 很多 特 性(property) 和 方 法(method), 利 用 它 們 可 以 達 到 更 完 美 的 顯 示 效 果,, 有 興趣 的 讀 者 可 以 進 一 步 研 究,。 不 管 是 開 發(fā) 什 么 樣 的 應(yīng) 用 程 序, 只 有 堅 持 面 向 用 戶,、方 便 用 戶 的 原 則,, 這 樣 的 軟 件 才 具 有 強 大 的 生 命 力。