自製 ProgressBar 控制項(二)讓控制項能隨容器背景色自動變化色彩

自製 ProgressBar 控制項(二)

前文「自製 ProgressBar 控制項」貼出後,總覺得還有很多地方要加強,例如下面:


  1. 要有自動配色功能,可以簡化一些色彩上面的視覺調整,尤其是團隊分工時只要規範了主色就能達到視覺上的一致性,以下是一些想增加的功能:
    1. 設計階段就要生效)自動配色在程式編輯階段就能發生作用,以便觀察效果進行調整。
    2. 主動配色)將控制項加入至容器時,能立即根據容器的 BackColor 配出適合的色彩把自己裝扮起來。
    3. 被動變色)於控制項加入至容器後,能隨時偵測容器的 BackColor 是否發生改變,若父容器底色有異動就處理。
    4. 可選擇性)自動配色功能可經由屬性控制是否生效。

      設計階段加入到不同背景的容器時,當下就會變色。
      image_thumb image_thumb1

      設計階段加入到不同背景的容器時。 執行階段改變容器背景色時。 
      image_thumb4 image_thumb11
  2. 另外再為進度 Bar 增加一組連續方格的樣式,像是早期的 VB6 .
    1. 小方格寬度隨控制項的 Width 適度做比例調整。

      image_thumb3

 


程式碼部分基本上和前文大致相同,但改用了 Panel 做為最下層容器及「已運行」及「未運行」色塊都改用了 Label。

  1. 配色的部分用到了 Color 的 HSL 擴充(http://www.dotblogs.com.tw/ku3/archive/2011/08/05/32618.aspx):

    
        '---介面條件改變時調整配色---
        Private Sub 更新介面() Handles Me.SizeChanged, Me.ForeColorChanged, Me.BackColorChanged
            Dim 基色 As Color = IIf(new_自動配色, new_自動前景色, new_手動前景色)
            Dim 亮色 As Color = 取出亮色(基色)
            Dim 暗色 As Color = 取出暗色(基色)
            Dim 中色 As Color = 取出中色(基色)
            lbl_未運行區域.BackColor = IIf(new_自動配色, 取出底色(基色), Me.BackColor)
            lbl_已運行區域.BackColor = 暗色
            Select Case new_顯示樣式
                Case 色塊樣式.連續立體
                    漸層圖 = 新建漸層色塊(10, 20, 暗色, 亮色, 90)
                    lbl_已運行區域.BackgroundImage = 漸層圖
                    lbl_已運行區域.BackgroundImageLayout = ImageLayout.Stretch
                Case 色塊樣式.連續方格, 色塊樣式.連續方格
                    Dim 方塊寬度 As Integer = Me.Width / 60
                    If 方塊寬度 < 4 Then 方塊寬度 = 4
                    If 方塊寬度 > 8 Then 方塊寬度 = 8
                    漸層圖 = 新建漸層色塊(方塊寬度, lbl_已運行區域.Height, 暗色, 亮色, 180)
                    lbl_已運行區域.BackgroundImage = 漸層圖
                    lbl_已運行區域.BackgroundImageLayout = ImageLayout.Tile
                Case 色塊樣式.連續平面
                    lbl_已運行區域.BackColor = 中色
                    lbl_已運行區域.BackgroundImage = Nothing
            End Select
        End Sub
        Private Function 新建漸層色塊 _
        (ByVal w As Integer, ByVal h As Integer, ByVal 暗色 As Color, ByVal 亮色 As Color, ByVal 方向 As Integer) As Image
            Dim image As Bitmap = New System.Drawing.Bitmap(w, H)
            Dim g As Graphics = Graphics.FromImage(Image)
            Dim rect0 As New Rectangle(0, 0, Image.Size.Width, Image.Size.Height)
            '---決定圖塊樣式---
            If new_顯示樣式 = 色塊樣式.連續立體 Then
                Dim 色塊 As LinearGradientBrush = New LinearGradientBrush(rect0, 亮色, 暗色, 方向)
                g.FillRectangle(色塊, rect0)
            Else
                Dim 圖形模式 As New GraphicsPath
                圖形模式.AddRectangle(rect0)
                Dim 色塊 As New PathGradientBrush(圖形模式)
                色塊.CenterColor = 暗色
                色塊.SurroundColors = New Color() {亮色}
                g.FillRectangle(色塊, rect0)
            End If
            Return image
        End Function
    
        '---從基礎色彩中取出不同亮度的特定色---
        Function 取出底色(原色 As Color) As Color
            Return 原色.FromHSL(原色.H, 原色.S, 220)
        End Function
        Function 取出亮色(原色 As Color) As Color
            Return 原色.FromHSL(原色.H, 原色.S, 195)
        End Function
        Function 取出暗色(原色 As Color) As Color
            Return 原色.FromHSL(原色.H, 原色.S, 50)
        End Function
        Function 取出中色(原色 As Color) As Color
            Return 原色.FromHSL(原色.H, 原色.S, 60)
        End Function

  2. 偵測父容器背景:

    
        '---若父容器改變了就做以下動作---
        Private Sub 父容器改變(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.ParentChanged
            If Not IsNothing(sender.Parent) Then
                RemoveHandler 父容器.BackColorChanged, AddressOf 父容器背景色改變  '---先移除原父容器的事件程序---
                父容器 = sender.parent                                             '---取得新容器---
                AddHandler 父容器.BackColorChanged, AddressOf 父容器背景色改變     '---建立新的事件程序---
                new_自動前景色 = 父容器.BackColor
                更新介面()
            End If
        End Sub
        '---若父容器背景色發生改變---
        Private Sub 父容器背景色改變(ByVal sender As Object, ByVal e As System.EventArgs)
            If new_自動配色 Then
                new_自動前景色 = sender.backcolor
                更新介面()
            End If
        End Sub

  3. 屬性存取部分:

    
    #Region "---屬性---"
        Sub 秀出關於畫面()
            If Not IsNothing(ParentForm) Then
                Dim f = New frm_About
                f.ShowDialog()
            End If
        End Sub
        <Description("關於 ku_ProgressBar ..."), Browsable(True), Category("行為")> _
        Public Property 關於() As 關於_觸發變數
            Get
                Return new_關於樣式
            End Get
            Set(value As 關於_觸發變數)
                If value = 關於_觸發變數.開啟 Then
                    秀出關於畫面()
                End If
            End Set
        End Property
        <Description("最大設定值"), Browsable(True), Category("行為")> _
            Public Property 最大設定值() As Integer
            Get
                Return new_最大設定值
            End Get
            Set(value As Integer)
                new_最大設定值 = value
                更新進度()
            End Set
        End Property
        <Description("最小設定值"), Browsable(True), Category("行為")> _
        Public Property 最小設定值() As Integer
            Get
                Return new_最小設定值
            End Get
            Set(ByVal value As Integer)
                new_最小設定值 = value
                更新進度()
            End Set
        End Property
        <Description("當下進度值"), Browsable(True), Category("行為")> _
        Public Property 當下進度值() As Single
            Get
                Return Math.Round(new_當下進度值, 2)
            End Get
            Set(ByVal value As Single)
                If value < new_最小設定值 Then value = new_最小設定值
                If value > new_最大設定值 Then value = new_最大設定值
                new_當下進度值 = value
                更新進度()
            End Set
        End Property
        <Description("非自動配色時進度列的前景色"), Browsable(True), Category("外觀")> _
        Public Overloads Property ForeColor() As Color
            Get
                Return new_手動前景色
            End Get
            Set(ByVal value As Color)
                new_手動前景色 = value
                MyBase.ForeColor = value
            End Set
        End Property
        <Description("決定進度顯示樣式"), Browsable(True), Category("外觀")> _
        Public Property 顯示樣式() As 色塊樣式
            Get
                Return new_顯示樣式
            End Get
            Set(ByVal value As 色塊樣式)
                new_顯示樣式 = value
                更新介面()
            End Set
        End Property
        <Description("設為 True 時依據父容器的 BackColor 決定配色"), Browsable(True), Category("外觀")> _
        Public Property 自動配色() As Boolean
            Get
                Return new_自動配色
            End Get
            Set(ByVal value As Boolean)
                new_自動配色 = value
                更新介面()
            End Set
        End Property
    #End Region

 




ku3