利用VB2005制作顏色漸變的進(jìn)度條

字號(hào):

現(xiàn)在Windows環(huán)境下的應(yīng)用程序經(jīng)常要用到進(jìn)度條,用以指示出一些復(fù)雜進(jìn)程的運(yùn)行狀態(tài)。目前我們?cè)诖绑w設(shè)計(jì)時(shí),使用的都是單色進(jìn)度條。本文講述在WindowsXP環(huán)境下,使用VB2005制作一個(gè)漂亮的顏色漸變的進(jìn)度條組件。
    一.技術(shù)細(xì)節(jié)
    這種進(jìn)度條的顯示相當(dāng)于使用許多顏色相近的“畫(huà)筆”在窗體上繪制方框。這些“畫(huà)筆”就相當(dāng)于一個(gè)畫(huà)筆數(shù)組。首先要建立顏色數(shù)組,初始的時(shí)候放入一些顏色值,然后根據(jù)平滑度的設(shè)置來(lái)重新設(shè)置顏色數(shù)組。依次取出顏色數(shù)組中兩個(gè)相鄰的顏色值,計(jì)算這兩個(gè)顏色經(jīng)過(guò)混合后的顏色,再放入到兩個(gè)顏色的中間。例子中顏色數(shù)組中有8種顏色。平滑度的值從0開(kāi)始循環(huán),是7。每經(jīng)過(guò)一次循環(huán),顏色數(shù)組中就增加了一些過(guò)渡顏色。平滑度設(shè)置的越大,則顏色過(guò)渡的越柔和。產(chǎn)生的效果越漂亮。顏色數(shù)組生成之后,畫(huà)筆數(shù)組就確定了。它的大小和顏色數(shù)組一致。有了畫(huà)筆數(shù)組,下面的問(wèn)題就是在窗體上進(jìn)行繪圖操作了。
    二、實(shí)現(xiàn)原理
    在繪圖操作之前。所以要重載基類(lèi)中的窗體的消息處理事件WndProc,窗體大小變化事件OnResize和窗體重繪事件OnPaint。加入以下屬性設(shè)置:
    Minimum。表示進(jìn)度條的最小值。默認(rèn)是 0 。
    Maximum。表示進(jìn)度條的值。默認(rèn)是 100 。
    Value。表示了進(jìn)度條的當(dāng)前值。默認(rèn)是 0 。
    Smoothness。表示了進(jìn)度條顏色漸變的平滑度。默認(rèn)是 0 。
    在初始化的時(shí)候,設(shè)置了以上四個(gè)屬性后,相應(yīng)的畫(huà)筆數(shù)組產(chǎn)生了。當(dāng)前值的每次改變都要觸發(fā)OnPaint事件。觸發(fā)事件后,首先繪制進(jìn)度條的外部邊框,接著得到內(nèi)部邊框的總寬度和高度。根據(jù)當(dāng)前值,最小值和值計(jì)算完成百分比,由完成百分比乘以總寬度得到當(dāng)前值占用的寬度??倢挾瘸援?huà)筆數(shù)組的個(gè)數(shù)得到每個(gè)畫(huà)筆所占用的寬度。然后就是從初始寬度循環(huán)到當(dāng)前值占用的寬度,從畫(huà)筆數(shù)組中依次使用畫(huà)筆按照每個(gè)畫(huà)筆所占用的寬度和高度填充顏色。循環(huán)結(jié)束后,如果百分比為100%。則使用畫(huà)筆數(shù)組中的最后一個(gè)畫(huà)筆繪制顏色。進(jìn)度條顯示完畢。
    三、實(shí)現(xiàn)步驟
    打開(kāi)VS2005,點(diǎn)擊“文件”下的“新建項(xiàng)目”,在打開(kāi)的窗體中,“項(xiàng)目類(lèi)型”選擇“Visual Basic”?!澳0濉边x擇“Windows 控件庫(kù)”。在左下角,“名稱(chēng)”改為“GradientProcessBar”。按下“確定”按鈕,新建工程。在“解決方案資源管理器”窗口中,將文件名UserControl1.vb 改為 GradientProcessBar.vb 。將下面完整的代碼加入到GradientProcessBar.vb文件中。
    Option Strict On
    Option Explicit On
    Imports System.Drawing
    Imports System.Windows.Forms
    Public Class GradientProcessBar
    Inherits UserControl
    Public Const MinSmoothness As Integer = 0   ’最小平滑度
    Public Const MaxSmoothness As Integer = 7   ’平滑度
    Private Const BorderWidth As Integer = 2    ’邊界寬度
    Private lstDefault As List(Of Color)    ’顏色數(shù)組
    Private lstBrushes As List(Of SolidBrush)   ’畫(huà)筆數(shù)組
    Private m_Value As Integer = 0  ’當(dāng)前進(jìn)度值
    Private m_Minimum As Integer = 0    ’最小進(jìn)度值
    Private m_Maximum As Integer = 100  ’進(jìn)度值
    Private m_Smoothness As Integer = 0 ’平滑度
    ’進(jìn)度值設(shè)置
    Public Property Value() As Integer
    Get
    Return m_Value
    End Get
    Set(ByVal value As Integer)
    m_Value = value
    If m_Value < m_Minimum Then m_Value = m_Minimum
    If m_Value > m_Maximum Then m_Value = m_Maximum
    Me.Invalidate(False)
    End Set
    End Property
    ’最小值設(shè)置
    Public Property Minimum() As Integer
    Get
    Return m_Minimum
    End Get
    Set(ByVal value As Integer)
    m_Minimum = value
    If m_Minimum > m_Maximum Then Swap(m_Minimum, m_Maximum)
    If m_Value < m_Minimum Then m_Value = m_Minimum
    Me.Invalidate(False)
    End Set
    End Property
    ’值設(shè)置
    Public Property Maximum() As Integer
    Get
    Return m_Maximum
    End Get
    Set(ByVal value As Integer)
    m_Maximum = value
    If m_Minimum > m_Maximum Then Swap(m_Minimum, m_Maximum)
    If m_Value > m_Maximum Then m_Value = m_Maximum
    Me.Invalidate(False)
    End Set
    End Property
    ’平滑度設(shè)置
    Public Property Smoothness() As Integer
    Get
    Return m_Smoothness
    End Get
    Set(ByVal value As Integer)
    If value < GradientProcessBar.MinSmoothness Then value = MinSmoothness
    If value > GradientProcessBar.MaxSmoothness Then value = MaxSmoothness
    m_Smoothness = value
    BuildColorList(lstDefault)
    Me.Invalidate(False)
    End Set
    End Property
    ’交換值
    Private Sub Swap(ByRef val1 As Integer, ByRef val2 As Integer)
    Dim temp As Integer
    temp = val1
    val1 = val2
    val2 = temp
    End Sub
    Public Sub New()
    InitializeComponent()
    Me.BorderStyle = Windows.Forms.BorderStyle.Fixed3D  ’設(shè)置窗體為凹陷的效果
    ’最簡(jiǎn)單的實(shí)現(xiàn)雙緩沖繪圖
    ’AllPaintingInWmPaint 忽略系統(tǒng)消息,防止圖像閃爍
    ’DoubleBuffer 設(shè)置雙緩沖,防止圖像抖動(dòng)
    ’UserPaint 自己為控件做所有的繪圖操作
    ’Opaque 使窗體繪制時(shí),不繪制背景  Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer Or ControlStyles.Opaque, True)
    ’更新風(fēng)格
    Me.UpdateStyles()
    ’新建顏色列表,加入紅色,桔黃色,黃色,綠色,藍(lán)綠色,藍(lán)色,深藍(lán)色,紫色
    lstDefault = New List(Of Color)
    lstDefault.Add(Color.Red)
    lstDefault.Add(Color.Orange)
    lstDefault.Add(Color.Yellow)
    lstDefault.Add(Color.Green)
    lstDefault.Add(Color.Cyan)
    lstDefault.Add(Color.Blue)
    lstDefault.Add(Color.Indigo)
    lstDefault.Add(Color.Violet)
    Value = Minimum
    End Sub
    ’將兩個(gè)顏色值混合成一個(gè)新的顏色。
    Private Function MixColors(ByVal color1 As Color, ByVal color2 As Color) As Color
    Return Color.FromArgb(CInt((CInt(color1.R) + CInt(color2.R)) / 2), CInt((CInt(color1.G) + CInt(color2.G)) / 2), CInt((CInt(color1.B) + CInt(color2.B)) / 2))
    End Function
    ’建立顏色數(shù)組和畫(huà)筆數(shù)組
    Private Sub BuildColorList(ByRef lstAdd As List(Of Color))
    Dim c As Color
    Dim lstColors As New List(Of Color)
    lstBrushes = New List(Of SolidBrush)
    For Each c In lstAdd
    lstColors.Add(c)
    Next
    Dim idx As Integer ’顏色數(shù)組索引
    Dim cnt As Integer ’顏色數(shù)組長(zhǎng)度
    Dim sdc As Integer ’平滑度索引
    ’根據(jù)平衡度的不同創(chuàng)建顏色數(shù)組
    For sdc = 0 To m_Smoothness Step 1
    idx = 0
    cnt = lstColors.Count - 1
    While idx < cnt
    lstColors.Insert(idx + 1, MixColors(lstColors(idx), lstColors(idx + 1)))
    idx += 2
    cnt += 1
    End While
    Next sdc
    ’根據(jù)顏色數(shù)組創(chuàng)建畫(huà)筆數(shù)組
    For Each c In lstColors
    lstBrushes.Add(New SolidBrush(c))
    Next
    End Sub
    ’重載消息處理事件。
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If m.Msg = &H14 Then
    Return
    End If
    MyBase.WndProc(m)
    End Sub
    ’重載窗口寸改變事件
    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
    MyBase.OnResize(e)
    Me.Invalidate(False)
    End Sub
    ’重載窗口繪制事件
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaint(e)
    ’繪制外框
    e.Graphics.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
    ’完成百分比
    Dim percentComplete As Single = CSng((m_Value - m_Minimum) / (m_Maximum - m_Minimum))
    If percentComplete <= 0.0F Then Exit Sub
    If percentComplete > 1.0F Then percentComplete = 1.0F
    Dim fullWidth As Single
    ’總寬度
    fullWidth = CSng(Me.ClientRectangle.Width - BorderWidth)
    ’當(dāng)前百分比所占用的寬度
    Dim totalWidth As Single = fullWidth * percentComplete
    ’每個(gè)畫(huà)筆填充顏色占用的寬度
    Dim barWidth As Single
    barWidth = fullWidth
    barWidth /= CSng(lstBrushes.Count)
    Dim height As Single  ’起始寬度
    Dim halfBorder As Single = CSng(BorderWidth / 2)
    Dim idxColor As Integer = 0
    Dim x As Single
    ’每個(gè)畫(huà)筆填充顏色占用的寬度
    height = CSng(Me.ClientRectangle.Height - BorderWidth)
    ’根據(jù)當(dāng)前百分比所占用的寬度使用畫(huà)筆填充顏色
    For x = halfBorder To totalWidth Step barWidth
    e.Graphics.FillRectangle(lstBrushes(idxColor), x, halfBorder, barWidth, height)
    If idxColor < lstBrushes.Count Then
    idxColor += 1
    End If
    Next
    ’當(dāng)進(jìn)度為100%的,使用最后一個(gè)畫(huà)筆填充顏色.
    If (x < (Me.ClientRectangle.Width - halfBorder)) And percentComplete = 1.0 Then
    If idxColor < lstBrushes.Count Then
    e.Graphics.FillRectangle(lstBrushes(idxColor), x, halfBorder, ((Me.ClientRectangle.Width - halfBorder) - x), height)
    End If
    End If
    End Sub
    End Class
    保存項(xiàng)目后,按下“生成”菜單中的“生成 GradientProcessBar”選項(xiàng),生成了組件GradientProcessBar.dll。
    四、測(cè)試組件
    點(diǎn)擊“文件”下的“新建項(xiàng)目”,在打開(kāi)的窗體中,“項(xiàng)目類(lèi)型”選擇“Visual Basic”。“模板”選擇“Windows 應(yīng)用程序”。在左下角,“名稱(chēng)”改為“Test”。按下“確定”按鈕,新建工程。在打開(kāi)的窗體Form1.vb中,加入一個(gè)Button控件,設(shè)置屬性Text=啟動(dòng)。一個(gè)Label控件,設(shè)置屬性Text=當(dāng)前進(jìn)度。一個(gè)Timer控件。點(diǎn)擊“工具”菜單下的“選擇工具箱項(xiàng)”。點(diǎn)擊 “.NET Framework 組件”頁(yè)。點(diǎn)擊“瀏覽”按鈕。選擇剛才生成的榧礼radientProcessBar.dll加入到窗體中。如下圖示:
    http://img.ddvip.com/2009_02_27/1235741535_ddvip_7994.jpeg
    點(diǎn)擊 “確定”按鈕。則在工具箱中有了GradientProcessBar 控件了。在窗體上加入一個(gè)
    GradientProcessBar控件。設(shè)置屬性Name=Pb1。在Form1.vb中添加如下代碼:
    Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    ’設(shè)置進(jìn)度條初始值
    Pb1.Minimum = 0
    Pb1.Maximum = 100
    Pb1.Value = 0
    Pb1.Smoothness = 4
    ’啟動(dòng)進(jìn)度條
    Timer1.Interval = 10
    Timer1.Enabled = True
    End Sub
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    ’顯示當(dāng)前進(jìn)度。
    Pb1.Value += 1
    Label1.Text = "當(dāng)前進(jìn)度:" + CStr(CInt(Pb1.Value / Pb1.Maximum * 100)) + "%"
    End Sub
    End Class
    按F5鍵運(yùn)行程序,顯示如下窗體: 
    
    按下“啟動(dòng)”按鈕,顯示當(dāng)前進(jìn)度,如下圖所示:  
    
    進(jìn)度條顯示完后,如下圖所示:  
    
    結(jié)束語(yǔ)
    本文對(duì)基于VB2005的組件編程技術(shù)作了初步的介紹,關(guān)于這方面的技術(shù)。有興趣的讀者可以參考相關(guān)的資料,為以后能開(kāi)發(fā)出更多更好的組件打下一定的基礎(chǔ)