1. 属性:
在缺省情况下,ListBox是不允许被重绘制的,这是因为ListBox中的“DrawMode”属性值是“Normal”。此属性的作用是设定ListBox的绘制模式,“Normal”是枚举DrawMode中的一个成员。设定为“Normal”意味着ListBox中各个成员都是系统控制,并且各项大小相等。“DrawMode”属性在本文中的作用类似与上一文中的“OwnerDraw”属性。枚举DrawMode中的其他成员请参阅表01所示:Net Frame Work SDK 为在VB.Net实现个性化ListBox提供的工具
属性 | 说明 |
Normal | 组件的所有元素都由操作系统绘制,并且元素大小都相等。 |
OwnerDrawFixed | 组件的所有元素都是手动绘制的,并且元素大小都相等。 |
OwnerDrawVariable | 组件的所有元素都由手动绘制,元素大小可能不相等。 |
本文设定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】项目设计界面之一 |
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项目名称Net Frame Work SDK 为在VB.Net实现个性化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】项目运行界面之一 |
在各项的指定位置绘制相应的图象,所以首先要确定上述六项对应的图象图片所在的位置,方便起见,这六个图片文件都和此项目编译后的文件在同一目录。名称分别为“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】项目运行界面之二 |
四.总结:
Net Frame Work SDK 为在VB.Net实现个性化ListBox提供的工具
通过本文可见,手动绘制Windows窗体组件并不像想像的那么复杂。由于.Net FrameWork SDK已经为Visual Basic .Net提供了许多绘制Windows窗体组件的“工具”,只要掌握Windows组件事件的处理过程和正常处理事件接收的参数中的数据,运用各种图形、图象的绘制方法,再加上精心的编排,就基本能够“改造”任何Windows窗体组件。