04
09 Jun.
带进度条的ListView,在Item中直接画Progress
最后更新: 2009/06/04 | 评论: 0 | 关键词: ListView Progress SubItem 进度条 重绘
重绘的确是个好东西,又长了些见识了。
最近因为做下载列表框,看了迅雷、快车啥的,在 ListView 中 加入进度条,那个帅啊,哈哈
其实很重就想做这个了,但是一直苦思找不到好的教材,加上自己水平欠佳啊,木办法,谁叫俺是个业余选手呢。
后来俺赶时髦,用上了 .Net,哇!爽!好适合俺这种懒人啊!
于是这几天 Google 来,Baidu 去,看看别人如何实现的,呵呵,不错找到了一个,地址俺给丢了,先向作者表示歉意哈。源代码是 C# 的。立马 C# 转 VB.Net 试试,呵呵,还行,东西出来了,不过呢,太差了,原来很多地方没有判断和处理,所以效果不好,于是俺就想啊。是不是俺也能仿造一个涅,恩哼,第一版出来了。直接重绘,自己画全部的 ListView,不过问题还是有很多,先上代码:
- '--------------------------------------------------
- '
- ' 窗体 - 带进度条的 ListView
- '
- ' namespace: WoodCoal.Library.Windows.Forms.ListViewProgress
- ' author: 木炭(WoodCoal)
- ' homepage: http://www.woodcoal.cn/
- ' memo: 带进度条的 ListView
- ' release: 2009-06-02
- '
- '--------------------------------------------------
- Namespace Windows.Forms
- Public Class ListViewProgress
- Inherits System.Windows.Forms.ListView
- '不能使用的属性
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows LargeImageList
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows SmallImageList
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows StateImageList
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows LabelEdit
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows View
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows ShowGroups
- <ComponentModel.Browsable(False), Obsolete()> _
- Public Shadows Groups
- '---------------------------------------------
- ''' <summary>进度条内容</summary>
- Private _ProgressText As String
- ''' <summary>进度条背景色</summary>
- Private _ProgressBackColor As Drawing.Color
- ''' <summary>进度条文字色</summary>
- Private _ProgressTextColor As Drawing.Color
- ''' <summary>进度条的序列</summary>
- Private _ProgressColumnIndex As Integer = -1
- '----------------------------------------------------------------
- Public Sub New()
- SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint Or System.Windows.Forms.ControlStyles.DoubleBuffer Or System.Windows.Forms.ControlStyles.UserPaint Or System.Windows.Forms.ControlStyles.ResizeRedraw, True)
- Me.Name = "ProgressListView"
- Me.ProgressBackColor = Drawing.Color.FromKnownColor(Drawing.KnownColor.Highlight)
- Me.ProgressTextColor = MyBase.ForeColor
- MyBase.View = System.Windows.Forms.View.Details
- AddHandler Me.Click, AddressOf Me.ListView_Click
- AddHandler Me.Paint, AddressOf Me.ListView_Paint
- End Sub
- '----------------------------------------------------------------
- ''' <summary>进度条背景色</summary>
- Public Property ProgressBackColor() As Drawing.Color
- Get
- Return _ProgressBackColor
- End Get
- Set(ByVal value As Drawing.Color)
- _ProgressBackColor = value
- End Set
- End Property
- ''' <summary>进度条文字色</summary>
- Public Property ProgressTextColor() As Drawing.Color
- Get
- Return _ProgressTextColor
- End Get
- Set(ByVal value As Drawing.Color)
- _ProgressTextColor = value
- End Set
- End Property
- ''' <summary>进度条的序列</summary>
- Public Property ProgressColumnIndex() As Integer
- Get
- Return _ProgressColumnIndex
- End Get
- Set(ByVal value As Integer)
- _ProgressColumnIndex = value
- End Set
- End Property
- ''' <summary>ImageList</summary>
- Public Overloads Property ImageList() As System.Windows.Forms.ImageList
- Get
- Return MyBase.SmallImageList
- End Get
- Set(ByVal value As System.Windows.Forms.ImageList)
- MyBase.SmallImageList = value
- End Set
- End Property
- '----------------------------------------------------------------
- ''' <summary>
- ''' 重绘
- ''' </summary>
- ''' <param name="sender"></param>
- ''' <param name="e"></param>
- ''' <remarks></remarks>
- Private Sub ListView_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
- '清除背景
- e.Graphics.Clear(MyBase.BackColor)
- '检查是否有项目,无项目直接退出
- If MyBase.Columns.Count < 1 Then Exit Sub
- '检查头部宽度
- If MyBase.SmallImageList IsNot Nothing Then
- If MyBase.Columns(0).Width < MyBase.SmallImageList.ImageSize.Width + 10 Then MyBase.Columns(0).Width = MyBase.SmallImageList.ImageSize.Width + 10
- End If
- '重绘所有行
- For Each Item As System.Windows.Forms.ListViewItem In MyBase.Items
- '获取区域
- Dim ItemRect As Drawing.Rectangle = MyBase.GetItemRect(Item.Index)
- '检查区域是否需要重绘
- If ItemRect <> Drawing.Rectangle.Empty And ItemRect.Top <= Me.ClientRectangle.Height And ItemRect.Top > 0 Then
- '获取图标
- Dim Image As Drawing.Image = Nothing
- Dim ImageSize As New Drawing.Size
- If MyBase.SmallImageList IsNot Nothing Then
- ImageSize = MyBase.SmallImageList.ImageSize
- If Not String.IsNullOrEmpty(Item.ImageKey) Then
- Image = MyBase.SmallImageList.Images(Item.ImageKey)
- ElseIf Item.ImageIndex > -1 Then
- Image = MyBase.SmallImageList.Images(Item.ImageIndex)
- End If
- End If
- '重绘图标
- If Image IsNot Nothing Then e.Graphics.DrawImage(Image, ItemRect.Left + 5, ItemRect.Top + 1, ImageSize.Width, ImageSize.Height)
- '调整大小
- If ItemRect.Width > ImageSize.Width + 8 Then
- ItemRect = New Drawing.Rectangle(ItemRect.Left + ImageSize.Width + 8, ItemRect.Top, ItemRect.Width - ImageSize.Width - 8, ItemRect.Height)
- Else
- ItemRect = Drawing.Rectangle.Empty
- End If
- '子项目左侧位置
- Dim SubItemLeft As Integer = ItemRect.Left
- For Each Column As System.Windows.Forms.ColumnHeader In MyBase.Columns
- Dim SubItemWidth As Integer = Column.Width
- If Column.Index = 0 Then SubItemWidth -= (ImageSize.Width + 8)
- '检查此列是否需要显示
- If SubItemLeft + SubItemWidth >= 0 Then
- '首列信息
- Dim SubItemRect As New Drawing.Rectangle(SubItemLeft, ItemRect.Top, Column.Width, ItemRect.Height)
- Dim SubItem As System.Windows.Forms.ListViewItem.ListViewSubItem = Item.SubItems(Column.Index)
- Dim SubItemColor As Drawing.Color = SubItem.ForeColor
- Dim SubItemText As String = SubItem.Text
- Dim SubItemAlign As System.Windows.Forms.HorizontalAlignment = Column.TextAlign
- '当前项目已经选中
- If Item.Selected And (Column.Index = 0 Or MyBase.FullRowSelect) Then
- SubItemColor = Drawing.Color.FromKnownColor(Drawing.KnownColor.HighlightText)
- e.Graphics.FillRectangle(New System.Drawing.SolidBrush(Drawing.Color.FromKnownColor(Drawing.KnownColor.Highlight)), SubItemRect)
- Else
- '用背景色填充
- e.Graphics.FillRectangle(New System.Drawing.SolidBrush(SubItem.BackColor), SubItemRect)
- End If
- '区域不为空
- If SubItemRect <> Drawing.Rectangle.Empty Then
- '检查当前项目是不是进度条
- If Column.Index = _ProgressColumnIndex Then
- '绘制进度条
- '绘制进度条的最小区域
- If SubItemRect.Height > 6 AndAlso SubItemRect.Width > 6 Then
- '调整为新的区域,以便产生一定的间距
- SubItemRect = New Drawing.Rectangle(SubItemRect.Left + 2, SubItemRect.Top + 2, SubItemRect.Width - 5, SubItemRect.Height - 5)
- Dim Percent As Single = 0
- If Common.String.Validate.Number(SubItemText) Then
- Percent = Single.Parse(SubItemText)
- If Percent >= 1.0F Then Percent = Percent / 100.0F
- End If
- '转换成百分比值
- SubItemText = Percent.ToString("p1")
- '外框
- e.Graphics.FillRectangle(Drawing.Brushes.White, SubItemRect)
- e.Graphics.DrawRectangle(New Drawing.Pen(Me.ForeColor), SubItemRect)
- '内容
- Dim ProgressRect As New Drawing.Rectangle(SubItemRect.Left + 1, SubItemRect.Top + 1, CInt((SubItemRect.Width * Percent)) - 1, SubItemRect.Height - 1)
- e.Graphics.FillRectangle(New Drawing.SolidBrush(_ProgressBackColor), ProgressRect)
- '重设颜色和位置
- SubItemColor = SubItem.ForeColor
- SubItemAlign = System.Windows.Forms.HorizontalAlignment.Center
- SubItemRect = New Drawing.Rectangle(SubItemRect.Left + 1, SubItemRect.Top + 1, SubItemRect.Width - 1, SubItemRect.Height - 1)
- End If
- End If
- '绘制文本
- If Not String.IsNullOrEmpty(SubItemText) Then
- '获取文字区域的实际大小
- If SubItem.Font.Height < SubItemRect.Height Then
- SubItemRect = New Drawing.Rectangle(SubItemRect.Left, SubItemRect.Top - Int(-(SubItemRect.Height - SubItem.Font.Height) / 2), SubItemRect.Width, SubItem.Font.Height)
- End If
- '输出文字
- Using StringFormat As New Drawing.StringFormat
- Select Case SubItemAlign
- Case System.Windows.Forms.HorizontalAlignment.Center
- StringFormat.Alignment = Drawing.StringAlignment.Center
- Case System.Windows.Forms.HorizontalAlignment.Left
- StringFormat.Alignment = Drawing.StringAlignment.Near
- Case System.Windows.Forms.HorizontalAlignment.Right
- StringFormat.Alignment = Drawing.StringAlignment.Far
- End Select
- StringFormat.LineAlignment = Drawing.StringAlignment.Center
- StringFormat.Trimming = Drawing.StringTrimming.EllipsisCharacter
- e.Graphics.DrawString(SubItemText, SubItem.Font, New System.Drawing.SolidBrush(SubItemColor), SubItemRect, StringFormat)
- End Using
- End If
- End If
- End If
- '下一列的 Left
- SubItemLeft += SubItemWidth
- Next
- End If
- Next
- End Sub
- '----------------------------------------------------------------
- Private Sub ListView_Click(ByVal sender As Object, ByVal e As System.EventArgs)
- MyBase.Invalidate()
- End Sub
- End Class
- End Namespace
使用很简单,创建 WoodCoal.Library.Windows.Forms.ListViewProgress 对象,其余使用和原版 ListView 一样,参数也那样的设置,只是最后指定一下滚动条所在的列: Object.ProgressColumnIndex
这个最主要的问题就是第一行第一列如果有图标的话,如果需要在运行是切换图标,自己不移动滚动条或者重新选中此行,图标永远不会变化。反正感觉贼奇怪,希望高手指点一下!
此版本因为是自己全部重绘,所以很多功能没有实现了,比如说分组等等。
· 本文由 木炭 发布在《激情燃烧的木炭》 上,原文地址为:http://www.woodcoal.cn/technology/visual-basic/200964-23310-500.html(转载请保留本信息、全文内容和链接)
关于本文
- 作者:
- 来源:
- 时间:2009/06/04
- 关键词:ListView Progress SubItem 进度条 重绘
- 栏 目:Visual Basic
- 上一篇:带进度条的ListView,在SubItem中显示Progress
- 下一篇:非对称加密算法(包含证书)加密解密签名验签
发表评论