技术 - Visual Basic - 带进度条的ListView,在Item中直接画Progress

04
09 Jun.

带进度条的ListView,在Item中直接画Progress

最后更新: 2009/06/04  |  评论: 0  |  关键词: ListView  Progress  SubItem  进度条  重绘  

重绘的确是个好东西,又长了些见识了。

最近因为做下载列表框,看了迅雷、快车啥的,在 ListView 中 加入进度条,那个帅啊,哈哈

其实很重就想做这个了,但是一直苦思找不到好的教材,加上自己水平欠佳啊,木办法,谁叫俺是个业余选手呢。

后来俺赶时髦,用上了 .Net,哇!爽!好适合俺这种懒人啊!

于是这几天 Google 来,Baidu 去,看看别人如何实现的,呵呵,不错找到了一个,地址俺给丢了,先向作者表示歉意哈。源代码是 C# 的。立马 C# 转 VB.Net 试试,呵呵,还行,东西出来了,不过呢,太差了,原来很多地方没有判断和处理,所以效果不好,于是俺就想啊。是不是俺也能仿造一个涅,恩哼,第一版出来了。直接重绘,自己画全部的 ListView,不过问题还是有很多,先上代码:

  1. '--------------------------------------------------     
  2. '     
  3. '   窗体 - 带进度条的 ListView  
  4. '     
  5. '   namespace: WoodCoal.Library.Windows.Forms.ListViewProgress  
  6. '   author: 木炭(WoodCoal)     
  7. '   homepage: http://www.woodcoal.cn/     
  8. '   memo: 带进度条的 ListView  
  9. '   release: 2009-06-02  
  10. '     
  11. '--------------------------------------------------   
  12.  
  13. Namespace Windows.Forms  
  14.     Public Class ListViewProgress  
  15.         Inherits System.Windows.Forms.ListView  
  16.  
  17.         '不能使用的属性  
  18.         <ComponentModel.Browsable(False), Obsolete()> _  
  19.         Public Shadows LargeImageList  
  20.  
  21.         <ComponentModel.Browsable(False), Obsolete()> _  
  22.         Public Shadows SmallImageList  
  23.  
  24.         <ComponentModel.Browsable(False), Obsolete()> _  
  25.          Public Shadows StateImageList  
  26.  
  27.         <ComponentModel.Browsable(False), Obsolete()> _  
  28.         Public Shadows LabelEdit  
  29.  
  30.         <ComponentModel.Browsable(False), Obsolete()> _  
  31.         Public Shadows View  
  32.  
  33.         <ComponentModel.Browsable(False), Obsolete()> _  
  34.         Public Shadows ShowGroups  
  35.  
  36.         <ComponentModel.Browsable(False), Obsolete()> _  
  37.         Public Shadows Groups  
  38.  
  39.         '---------------------------------------------  
  40.  
  41.         ''' <summary>进度条内容</summary>  
  42.         Private _ProgressText As String 
  43.  
  44.         ''' <summary>进度条背景色</summary>  
  45.         Private _ProgressBackColor As Drawing.Color  
  46.  
  47.         ''' <summary>进度条文字色</summary>  
  48.         Private _ProgressTextColor As Drawing.Color  
  49.  
  50.         ''' <summary>进度条的序列</summary>  
  51.         Private _ProgressColumnIndex As Integer = -1  
  52.  
  53.         '----------------------------------------------------------------  
  54.  
  55.         Public Sub New()  
  56.             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)  
  57.  
  58.             Me.Name = "ProgressListView" 
  59.             Me.ProgressBackColor = Drawing.Color.FromKnownColor(Drawing.KnownColor.Highlight)  
  60.             Me.ProgressTextColor = MyBase.ForeColor  
  61.             MyBase.View = System.Windows.Forms.View.Details  
  62.  
  63.             AddHandler Me.Click, AddressOf Me.ListView_Click  
  64.             AddHandler Me.Paint, AddressOf Me.ListView_Paint  
  65.         End Sub 
  66.  
  67.         '----------------------------------------------------------------  
  68.  
  69.         ''' <summary>进度条背景色</summary>  
  70.         Public Property ProgressBackColor() As Drawing.Color  
  71.             Get 
  72.                 Return _ProgressBackColor  
  73.             End Get 
  74.             Set(ByVal value As Drawing.Color)  
  75.                 _ProgressBackColor = value  
  76.             End Set 
  77.         End Property 
  78.  
  79.         ''' <summary>进度条文字色</summary>  
  80.         Public Property ProgressTextColor() As Drawing.Color  
  81.             Get 
  82.                 Return _ProgressTextColor  
  83.             End Get 
  84.             Set(ByVal value As Drawing.Color)  
  85.                 _ProgressTextColor = value  
  86.             End Set 
  87.         End Property 
  88.  
  89.         ''' <summary>进度条的序列</summary>  
  90.         Public Property ProgressColumnIndex() As Integer 
  91.             Get 
  92.                 Return _ProgressColumnIndex  
  93.             End Get 
  94.             Set(ByVal value As Integer)  
  95.                 _ProgressColumnIndex = value  
  96.             End Set 
  97.         End Property 
  98.  
  99.         ''' <summary>ImageList</summary>  
  100.         Public Overloads Property ImageList() As System.Windows.Forms.ImageList  
  101.             Get 
  102.                 Return MyBase.SmallImageList  
  103.             End Get 
  104.             Set(ByVal value As System.Windows.Forms.ImageList)  
  105.                 MyBase.SmallImageList = value  
  106.             End Set 
  107.         End Property 
  108.  
  109.         '----------------------------------------------------------------  
  110.  
  111.         ''' <summary>  
  112.         ''' 重绘  
  113.         ''' </summary>  
  114.         ''' <param name="sender"></param>  
  115.         ''' <param name="e"></param>  
  116.         ''' <remarks></remarks>  
  117.         Private Sub ListView_Paint(ByVal sender As ObjectByVal e As System.Windows.Forms.PaintEventArgs)  
  118.             '清除背景  
  119.             e.Graphics.Clear(MyBase.BackColor)  
  120.  
  121.             '检查是否有项目,无项目直接退出  
  122.             If MyBase.Columns.Count < 1 Then Exit Sub 
  123.  
  124.             '检查头部宽度  
  125.             If MyBase.SmallImageList IsNot Nothing Then 
  126.                 If MyBase.Columns(0).Width < MyBase.SmallImageList.ImageSize.Width + 10 Then MyBase.Columns(0).Width = MyBase.SmallImageList.ImageSize.Width + 10  
  127.             End If 
  128.  
  129.             '重绘所有行  
  130.             For Each Item As System.Windows.Forms.ListViewItem In MyBase.Items  
  131.                 '获取区域  
  132.                 Dim ItemRect As Drawing.Rectangle = MyBase.GetItemRect(Item.Index)  
  133.  
  134.                 '检查区域是否需要重绘  
  135.                 If ItemRect <> Drawing.Rectangle.Empty And ItemRect.Top <= Me.ClientRectangle.Height And ItemRect.Top > 0 Then 
  136.                     '获取图标  
  137.                     Dim Image As Drawing.Image = Nothing 
  138.                     Dim ImageSize As New Drawing.Size  
  139.  
  140.                     If MyBase.SmallImageList IsNot Nothing Then 
  141.                         ImageSize = MyBase.SmallImageList.ImageSize  
  142.                         If Not String.IsNullOrEmpty(Item.ImageKey) Then 
  143.                             Image = MyBase.SmallImageList.Images(Item.ImageKey)  
  144.                         ElseIf Item.ImageIndex > -1 Then 
  145.                             Image = MyBase.SmallImageList.Images(Item.ImageIndex)  
  146.                         End If 
  147.                     End If 
  148.  
  149.                     '重绘图标  
  150.                     If Image IsNot Nothing Then e.Graphics.DrawImage(Image, ItemRect.Left + 5, ItemRect.Top + 1, ImageSize.Width, ImageSize.Height)  
  151.  
  152.                     '调整大小  
  153.                     If ItemRect.Width > ImageSize.Width + 8 Then 
  154.                         ItemRect = New Drawing.Rectangle(ItemRect.Left + ImageSize.Width + 8, ItemRect.Top, ItemRect.Width - ImageSize.Width - 8, ItemRect.Height)  
  155.                     Else 
  156.                         ItemRect = Drawing.Rectangle.Empty  
  157.                     End If 
  158.  
  159.                     '子项目左侧位置  
  160.                     Dim SubItemLeft As Integer = ItemRect.Left  
  161.                     For Each Column As System.Windows.Forms.ColumnHeader In MyBase.Columns  
  162.                         Dim SubItemWidth As Integer = Column.Width  
  163.                         If Column.Index = 0 Then SubItemWidth -= (ImageSize.Width + 8)  
  164.  
  165.                         '检查此列是否需要显示  
  166.                         If SubItemLeft + SubItemWidth >= 0 Then 
  167.                             '首列信息  
  168.                             Dim SubItemRect As New Drawing.Rectangle(SubItemLeft, ItemRect.Top, Column.Width, ItemRect.Height)  
  169.                             Dim SubItem As System.Windows.Forms.ListViewItem.ListViewSubItem = Item.SubItems(Column.Index)  
  170.                             Dim SubItemColor As Drawing.Color = SubItem.ForeColor  
  171.                             Dim SubItemText As String = SubItem.Text  
  172.                             Dim SubItemAlign As System.Windows.Forms.HorizontalAlignment = Column.TextAlign  
  173.  
  174.                             '当前项目已经选中  
  175.                             If Item.Selected And (Column.Index = 0 Or MyBase.FullRowSelect) Then 
  176.                                 SubItemColor = Drawing.Color.FromKnownColor(Drawing.KnownColor.HighlightText)  
  177.                                 e.Graphics.FillRectangle(New System.Drawing.SolidBrush(Drawing.Color.FromKnownColor(Drawing.KnownColor.Highlight)), SubItemRect)  
  178.                             Else 
  179.                                 '用背景色填充  
  180.                                 e.Graphics.FillRectangle(New System.Drawing.SolidBrush(SubItem.BackColor), SubItemRect)  
  181.                             End If 
  182.  
  183.                             '区域不为空  
  184.                             If SubItemRect <> Drawing.Rectangle.Empty Then 
  185.                                 '检查当前项目是不是进度条  
  186.                                 If Column.Index = _ProgressColumnIndex Then 
  187.                                     '绘制进度条  
  188.                                     '绘制进度条的最小区域  
  189.                                     If SubItemRect.Height > 6 AndAlso SubItemRect.Width > 6 Then 
  190.                                         '调整为新的区域,以便产生一定的间距  
  191.                                         SubItemRect = New Drawing.Rectangle(SubItemRect.Left + 2, SubItemRect.Top + 2, SubItemRect.Width - 5, SubItemRect.Height - 5)  
  192.                                         Dim Percent As Single = 0  
  193.                                         If Common.String.Validate.Number(SubItemText) Then 
  194.                                             Percent = Single.Parse(SubItemText)  
  195.                                             If Percent >= 1.0F Then Percent = Percent / 100.0F  
  196.                                         End If 
  197.                                         '转换成百分比值  
  198.                                         SubItemText = Percent.ToString("p1")  
  199.  
  200.                                         '外框  
  201.                                         e.Graphics.FillRectangle(Drawing.Brushes.White, SubItemRect)  
  202.                                         e.Graphics.DrawRectangle(New Drawing.Pen(Me.ForeColor), SubItemRect)  
  203.  
  204.                                         '内容  
  205.                                         Dim ProgressRect As New Drawing.Rectangle(SubItemRect.Left + 1, SubItemRect.Top + 1, CInt((SubItemRect.Width * Percent)) - 1, SubItemRect.Height - 1)  
  206.                                         e.Graphics.FillRectangle(New Drawing.SolidBrush(_ProgressBackColor), ProgressRect)  
  207.  
  208.                                         '重设颜色和位置  
  209.                                         SubItemColor = SubItem.ForeColor  
  210.                                         SubItemAlign = System.Windows.Forms.HorizontalAlignment.Center  
  211.  
  212.                                         SubItemRect = New Drawing.Rectangle(SubItemRect.Left + 1, SubItemRect.Top + 1, SubItemRect.Width - 1, SubItemRect.Height - 1)  
  213.                                     End If 
  214.                                 End If 
  215.  
  216.                                 '绘制文本  
  217.                                 If Not String.IsNullOrEmpty(SubItemText) Then 
  218.                                     '获取文字区域的实际大小  
  219.                                     If SubItem.Font.Height < SubItemRect.Height Then 
  220.                                         SubItemRect = New Drawing.Rectangle(SubItemRect.Left, SubItemRect.Top - Int(-(SubItemRect.Height - SubItem.Font.Height) / 2), SubItemRect.Width, SubItem.Font.Height)  
  221.                                     End If 
  222.  
  223.                                     '输出文字  
  224.                                     Using StringFormat As New Drawing.StringFormat  
  225.                                         Select Case SubItemAlign  
  226.                                             Case System.Windows.Forms.HorizontalAlignment.Center  
  227.                                                 StringFormat.Alignment = Drawing.StringAlignment.Center  
  228.                                             Case System.Windows.Forms.HorizontalAlignment.Left  
  229.                                                 StringFormat.Alignment = Drawing.StringAlignment.Near  
  230.                                             Case System.Windows.Forms.HorizontalAlignment.Right  
  231.                                                 StringFormat.Alignment = Drawing.StringAlignment.Far  
  232.                                         End Select 
  233.  
  234.                                         StringFormat.LineAlignment = Drawing.StringAlignment.Center  
  235.                                         StringFormat.Trimming = Drawing.StringTrimming.EllipsisCharacter  
  236.  
  237.                                         e.Graphics.DrawString(SubItemText, SubItem.Font, New System.Drawing.SolidBrush(SubItemColor), SubItemRect, StringFormat)  
  238.                                     End Using  
  239.                                 End If 
  240.                             End If 
  241.                         End If 
  242.  
  243.                         '下一列的 Left  
  244.                         SubItemLeft += SubItemWidth  
  245.                     Next 
  246.                 End If 
  247.             Next 
  248.         End Sub 
  249.  
  250.         '----------------------------------------------------------------  
  251.  
  252.         Private Sub ListView_Click(ByVal sender As ObjectByVal e As System.EventArgs)  
  253.             MyBase.Invalidate()  
  254.         End Sub 
  255.     End Class 
  256. End Namespace 

使用很简单,创建 WoodCoal.Library.Windows.Forms.ListViewProgress 对象,其余使用和原版 ListView 一样,参数也那样的设置,只是最后指定一下滚动条所在的列: Object.ProgressColumnIndex

这个最主要的问题就是第一行第一列如果有图标的话,如果需要在运行是切换图标,自己不移动滚动条或者重新选中此行,图标永远不会变化。反正感觉贼奇怪,希望高手指点一下!

此版本因为是自己全部重绘,所以很多功能没有实现了,比如说分组等等。

· 本文由 木炭 发布在《激情燃烧的木炭》 上,原文地址为:http://www.woodcoal.cn/technology/visual-basic/200964-23310-500.html(转载请保留本信息、全文内容和链接)

发表评论

已经有 0 位朋友发表了对《带进度条的ListView,在Item中直接画Progress》的看法
 
登录名:  密码:   登录  注册
评论: 
User:
Contact:
验证码:  
  [Ctrl+Enter]

关于本文