ListBox(列表框)也是日常經常使用和遇到的組件,在Visual Basic .Net中使用的ListBox其實是從.Net FrameWork SDK中的ListBox類經過實例化產生的。.Net FrameWork SDK中的ListBox類所創建的ListBox是最典型的,要想使自己的ListBox與眾不同就必須編寫相應的代碼,好在.Net FrameWork SDK中的ListBox類為實現個性化的ListBox提供豐富的、可操作“工具”,這些“工具”就是繪制ListBox的所需要的事件、相關的屬性以及豐富的繪制方法。在本文中將介紹在ListBox中各個元素的繪制方法,其中包括繪制各種字體、顏色以及在各項上加上邊框和為各項加入圖片等。下面首先來了解一下.Net FrameWork SDK為在VB.Net中實現手工繪制ListBox提供的“工具”。
一..Net Frame Work SDK 為在VB.Net實現個性化ListBox提供的工具:
1. 屬性:
在缺省情況下,ListBox是不允許被重繪制的,這是因為ListBox中的“DrawMode”屬性值是“Normal”。此屬性的作用是設定ListBox的繪制模式,“Normal”是枚舉DrawMode中的一個成員。設定為“Normal”意味著ListBox中各個成員都是系統控制,並且各項大小相等。“DrawMode”屬性在本文中的作用類似與上一文中的“OwnerDraw”屬性。枚舉DrawMode中的其他成員請參閱表01所示:
屬性
說明
Normal 組件的所有元素都由操作系統繪制,並且元素大小都相等。 OwnerDrawFixed 組件的所有元素都是手動繪制的,並且元素大小都相等。 OwnerDrawVariable 組件的所有元素都由手動繪制,元素大小可能不相等。表01:枚舉DrawMode中的成員及其說明
本文設定ListBox的“DrawMode”屬性值是“OwnerDrawVariable”。因為本文介紹的程序不僅繪制ListBox中的各元素,還將設定ListBox中元素的大小。
2. 事件:
在設定“DrawMode”屬性值為“OwnerDrawVariable”後,將會觸發一些用以繪制ListBox的事件,如:DrawItem事件和MeasureItem事件。DrawItem事件主要處理繪制ListBox中的各個元素,MeasureItem事件主要是處理設置ListBox各元素的大小。ListBox中的DrawItem事件和MeasureItem事件和上一節中介紹的MenuItem的DrawItem事件和MeasureItem事件是一樣的,分別接收DrawItemEventArgs參數和MeasureItemEventArgs參數數據,並以此數據來處理。這二個事件的詳細介紹請參閱前一節中內容。
3. 繪制圖形的方法:
在繪制ListBox時所采用的方法和上一節中也基本相同,唯一不同的是在本文中增加了圖形繪制方法DrawImage,DrawImage方法的作用是在指定的位置,以指定圖形的原始大小進行繪制,本文通過DrawImage方法實現在ListBox各項中增加相應的圖形。
二.設計、調試和運行環境:
(1).微軟公司視窗2000服務器版。
(2).Visual Studio .Net 2003企業構建版,.Net FrameWork SDK 1.1版本號4322。
三.循序漸進繪制自己的ListBox:
首先還是按照以下步驟新建一個Visual Basic .Net項目,並在項目窗體上增加一個ListBox組件:
1. 啟動Visual Studio .Net。
2. 選擇菜單【文件】|【新建】|【項目】後,彈出【新建項目】對話框。
3. 將【項目類型】設置為【Visual Basic項目】。
4. 將【模板】設置為【Windows應用程序】。
5. 在【名稱】文本框中輸入【打造自己的ListBox】。
在【位置】的文本框中輸入【E:VS.NET項目】,然後單擊【確定】按鈕,這樣在“E:VS.NET項目”目錄中就產生了名稱為“打造自己的ListBox”的文件夾,並在裡面創建了名稱為“打造自己的ListBox”的項目文件。
6. 把Visual Studio .Net的當前窗口切換到【Form1.vb(設計)】窗口,並從【工具箱】中的【Windows窗體組件】選項卡中往Form1窗體中拖入一個ListBox組件到窗體中。並設定此ListBox組件中加入“aaa”、“bbb”和“ccc”三個項。
至此一個最典型的ListBox就完成了。具體如圖01所示:
圖01:【打造自己的ListBox】項目設計界面之一
下面就在此ListBox基礎上,對其進行改造,加入個性化的東西,首先是對ListBox中的各項的字體、顏色等等進行改造。修改ListBox字體和顏色是通過DrawItem事件來實現的,使用DrawString方法把指定字體、大小、顏色在指定區域繪制文字。設定ListBox各元素的大小是通過MeasureItem事件實現的。以下是實現上述改造的具體操作步驟:
1. 設定ListBox組件的“DrawMode”屬性值為“OwnerDrawVariable”。此時會發現在ListBox組件加入的“aaa”、“bbb”和“ccc”三項均不顯示。這是因為當ListBox組件的“DrawMode”屬性值為“OwnerDrawVariable”,繪制ListBox的工作將不在由機器自動完成,而是通過ListBox的DrawItem事件來實現。
2. 把Visual Studio .Net的當前窗口切換到Form1.vb的代碼編輯窗口。
3. 在定義窗體組件的代碼區中添加下列代碼,下列代碼是定義二個數組,此數組的成員分別是設定ListBox中各項的名稱和定義各項名稱的顏色。
Private sData ( ) As String = {"紅色" , "藍色" , "黃色" , "綠色" , "黃綠色" , "灰色"}
'此數組是定義ListBox中各項的名稱
Private sColorData ( ) As Object = {System.Drawing.Color.Red , System.Drawing.Color.Blue , System.Drawing.Color.Yellow , System.Drawing.Color.Green , System.Drawing.Color.YellowGreen , System.Drawing.Color.SlateGray}
'此數組是定義各項名稱對應的顏色
4. 在InitializeComponent過程中的代碼後部添加下列代碼,下列代碼是以上面定義的sData數組來設定ListBox的各項名稱:
listBox1.DataSource = sData
5. 在InitializeComponent過程之後添加下列代碼,下列代碼是定義ListBox的DrawItem事件,通過此事件對ListBox中各項進行重新繪制:
Private Sub listBox1_DrawItem ( ByVal sender As Object , ByVal e As System.Windows.Forms.DrawItemEventArgs ) Handles listBox1.DrawItem
Dim datas As String ( ) = sData
Dim rc As RectangleF = New RectangleF ( e.Bounds.X + 1 , e.Bounds.Y + 1 , e.Bounds.Width - 5 , e.Bounds.Height - 3 )
Dim rc1 As Rectangle = New Rectangle ( e.Bounds.X + 1 , e.Bounds.Y + 1 , e.Bounds.Width - 5 , e.Bounds.Height - 3 )
e.DrawBackground ( )
'在選定項目上繪制選定背景色
'e.DrawFocusRectangle ( )
Dim sf As StringFormat = New StringFormat ( )
sf.Alignment = StringAlignment.Center
'設定ListBox中項目名稱的在矩形區域的排列對齊方式
e.Graphics.DrawRectangle ( New Pen ( New SolidBrush ( System.Drawing.Color.Black ) , 1 ) , rc1 )
'以線條粗度為1,黑色畫筆對繪制ListBox中的每一個項目的邊框
e.Graphics.DrawString ( sData ( e.Index ) , New Font ( FontFamily.GenericSansSerif , 14 , FontStyle.Bold ) , New SolidBrush ( sColorData ( e.Index ) ) , rc , sf )
' 以指定的字體大小、類型、顏色繪制ListBox項目名稱
End Sub
6. 在ListBox的DrawItem事件代碼之後添加下列代碼,下列代碼是定義ListBox的MeasureItem事件,此事件的作用是設定ListBox的各元素的大小:
Private Sub listBox1_MeasureItem ( ByVal sender As Object , ByVal e As System.Windows.Forms.MeasureItemEventArgs ) Handles listBox1.MeasureItem
e.ItemHeight = 25
End Sub
至此重新繪制的ListBox第一步就完成了,保存上述的修改後,單擊快捷鍵F5,改造後的ListBox如圖02所示:
圖02:【打造自己的ListBox】項目運行界面之一
下面就要實現為圖02中的每一項加入一個圖片,加入圖片的是通過DrawImage方法
在各項的指定位置繪制相應的圖象,所以首先要確定上述六項對應的圖象圖片所在的位置,方便起見,這六個圖片文件都和此項目編譯後的文件在同一目錄。名稱分別為“fileOpen.bmp”、“exit.bmp”、“close.bmp”、“about.bmp”、“about.bmp”和“network.bmp”。下面步驟就是在上述基礎上為各項加入圖片:
1. 在定義窗體組件的代碼區中再添加下列代碼,下列代碼是定義六個Bitmap對象:
Dim img_fileopen , img_exit , img_close , img_security , img_network , img_about As Bitmap
2. 在InitializeComponent過程中的代碼後部添加下列代碼,下列代碼是初始化上面創建的Bitmap對象:
'運行程序前確認在文件當前目錄存在以下六個BMP文件
img_fileopen = New Bitmap ( "fileOpen.bmp" )
img_exit = New Bitmap ( "exit.bmp" )
img_close = New Bitmap ( "close.bmp" )
img_about = New Bitmap ( "about.bmp" )
img_security = New Bitmap ( "about.bmp" )
img_network = New Bitmap ( "network.bmp" )
3. 用下列代碼替換Form1.vb中的ListBox1的DrawItem事件對應的代碼,下列代碼是重新定義ListBox1的DrawItem事件,其中增加了為ListBox1中各項添加圖片的功能:
Private Sub listBox1_DrawItem ( ByVal sender As Object , ByVal e As System.Windows.Forms.DrawItemEventArgs ) Handles listBox1.DrawItem
Dim datas As String ( ) = sData
Dim rc As RectangleF = New RectangleF ( e.Bounds.X + 1 , e.Bounds.Y + 1 , e.Bounds.Width - 5 , e.Bounds.Height - 3 )
Dim rc1 As Rectangle = New Rectangle ( e.Bounds.X + 1 , e.Bounds.Y + 1 , e.Bounds.Width - 5 , e.Bounds.Height - 3 )
e.DrawBackground ( )
'在選定項目上繪制選定背景色
'e.DrawFocusRectangle ( )
Dim sf As StringFormat = New StringFormat ( )
sf.Alignment = StringAlignment.Center
'設定ListBox中項目名稱的在矩形區域的排列對齊方式
e.Graphics.DrawRectangle ( New Pen ( New SolidBrush ( System.Drawing.Color.Black ) , 1 ) , rc1 )
'以線條粗度為1,黑色畫筆對繪制ListBox中的每一個項目的邊框
e.Graphics.DrawString ( sData ( e.Index ) , New Font ( FontFamily.GenericSansSerif , 14 , FontStyle.Bold ) , New SolidBrush ( sColorData ( e.Index ) ) , rc , sf )
' 以指定的字體大小、類型、顏色繪制ListBox項目名稱
Dim useImage As Image = Nothing
'創建、初始化一個Image實例
'以下是代碼是在ListBox上繪制圖片
If ( datas ( e.Index ) = "紅色" ) Then
useImage = img_fileopen
End If
If ( datas ( e.Index ) = "藍色" ) Then
useImage = img_close
End If
If ( datas ( e.Index ) = "黃色" ) Then
useImage = img_exit
End If
If ( datas ( e.Index ) = "綠色" ) Then
useImage = img_security
End If
If ( datas ( e.Index ) = "黃綠色" ) Then
useImage = img_network
End If
If ( datas ( e.Index ) = "灰色" ) Then
useImage = img_about
End If
If ( useImage Is Nothing ) = False Then
Dim sz As SizeF = New SizeF
sz = useImage.PhysicalDimension ( )
'獲取此Image實例的寬度和高度。
e.Graphics.DrawImage ( useImage , e.Bounds.X + 5 , CInt ( ( e.Bounds.Bottom + e.Bounds.Top ) / 2 - sz.Height / 2 ) )
'在制定的位置按照原始大小繪制圖片
End If
End Sub
保存上述步驟後,單擊快捷鍵F5,本文繪制後的ListBox如圖03所示:
圖03:【打造自己的ListBox】項目運行界面之二
四.總結:
通過本文可見,手動繪制Windows窗體組件並不像想像的那麼復雜。由於.Net FrameWork SDK已經為Visual Basic .Net提供了許多繪制Windows窗體組件的“工具”,只要掌握Windows組件事件的處理過程和正常處理事件接收的參數中的數據,運用各種圖形、圖象的繪制方法,再加上精心的編排,就基本能夠“改造”任何Windows窗體組件。