[Vb.net] 如何在表單顯示動態的圖示 Icon (三)製作圖片輪播控制項

雖然 VB.net 可以直接使用 GIF or SWF 呈現動畫效果,但為了顯示的流暢(同步)和能建立動態的表單圖示,和方便一些細節的控制,這裡還是自己做一個控制來用。
1.首先要建立一組或多組連續的影格來用。
2.為了應用上的方便我先把一系列的影格圖片合併成一張圖,要用時再根據圖寬除以圖高來得到共有多少個影格。
3.下面是幾個例子

雖然 VB.net 可以直接使用 GIF or SWF 呈現動畫效果,但為了顯示的流暢(同步)和能建立動態的表單圖示,方便一些細節的控制,這裡還是自己做一個控制來用。

  1. 首先要建立一組或多組連續的影格來用。
  2. 為了應用上的方便我先把一系列的影格圖片合併成一張圖,要用時再根據圖寬除以圖高來得到共有多少個影格。
  3. 下面是幾個例子:

    image
  4. 可以多做幾組放在專案的 Resource 裡面備用,並且為它們命名。

    image

 

程式碼部分:

  1. 挑選一個合適的 Control 來繼承,因為要做的圖片輪播器所以選用 PictureBox 為父類別,並讓它支援背景透明。
  2. 加一個 Timer 做為控制換圖時間週期的參考。
  3. 建構式如下:

    
        Public Sub New()
            MyBase.New()
            InitializeComponent()
            SetStyle(ControlStyles.SupportsTransparentBackColor, True)
            初始化圖檔資源()
            MyBase.Size = _擷取大小
        End Sub
        '---取出指定的圖檔並得到相關參數---
        Sub 初始化圖檔資源()
            _圖檔名稱 = "_" & _現用圖案ID.ToString
            _圖檔映像 = CType(My.Resources.ResourceManager.GetObject(_圖檔名稱), Bitmap)
            _圖檔映像.MakeTransparent()
            _擷取大小 = New Size(_圖檔映像.Height, _圖檔映像.Height)
            _畫格總數 = _圖檔映像.Width \ _圖檔映像.Height
            Timer1.Enabled = True
        End Sub
    


  4. 切換影格的程式碼如下:

    
        '---用 Timer 控制輪播影格---
        Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
            _當下畫格 = If(_當下畫格 < _畫格總數 - 1, _當下畫格 + 1, 0)
            播放單格(_當下畫格)
        End Sub
        '---根據圖號從圖檔中取出對應的部分放到自己的 Image 屬性---
        Sub 播放單格(Optional id As Integer = 0)
            MyBase.SizeMode = PictureBoxSizeMode.StretchImage
            Dim _擷取大小 = New Size(_圖檔映像.Height, _圖檔映像.Height)
            Dim 擷取位置 = New Point(id * _圖檔映像.Height, 0)
            Dim 矩形區域 = New Rectangle(擷取位置, _擷取大小)
            Dim 輸出圖樣 As Image = _圖檔映像.Clone(矩形區域, Imaging.PixelFormat.Format32bppArgb)
            RaiseEvent 圖像更新了(Me, CType(輸出圖樣, Bitmap))
            MyBase.Image = 輸出圖樣
        End Sub
    


  5. 屬性安排很陽春,只有選圖、設定速度,和一個讓外部得影格總數的 Integer:

    
    #Region "---屬性---"
        <Description("選擇動態圖樣式"), Browsable(True), Category("外觀")> _
        Public Property 設定圖形樣式() As 圖案樣式
            Get
                Return _現用圖案ID
            End Get
            Set(value As 圖案樣式)
                _現用圖案ID = value
                初始化圖檔資源()
            End Set
        End Property
        <Description("設定播放速度"), Browsable(True), Category("行為")> _
        Public Property 播放速度() As Integer
            Get
                Return _播放速度
            End Get
            Set(value As Integer)
                value = If(value < 1, 1, If(value > 500, 500, value))
                _播放速度 = value
                Timer1.Interval = value
                Timer1.Enabled = True
            End Set
        End Property
        <Description("取得播放畫格總數"), Browsable(True), Category("行為")> _
        Public ReadOnly Property 畫格總數() As Integer
            Get
                Return _畫格總數
            End Get
        End Property
    #End Region
    


  6. 宣告部分建立一組列舉,名稱和資源裡面的各張圖同名。
  7. 另外加一個回呼的事件告訴父端圖檔已經更新了。

    
    #Region "---宣告---"
        Public Enum 圖案樣式
            下載_灰
            下載_紅
            下載_綠
            下載_藍
            水滴_白
            水滴_紅
            水滴_綠
            水滴_藍
            地球_灰
            地球_綠
            地球_藍
            地球_藍灰
            星星_深灰
            星星_淺灰
            星星_黃
            風車_灰_直
            風車_灰_彎
            時針_黑_大
            時針_黑_小
            閃星_亮點
            圓箭_藍
            圓箭_雙藍
            齒輪_灰
            齒輪_棕
            齒輪_黑
            齒輪_綠
            齒輪_藍
            齒輪_雙輪
        End Enum
        Private _預設圖示 As Image
        Private _現用圖案ID As 圖案樣式 = 圖案樣式.下載_紅
        Private _播放速度 As Integer = 100
        Private _現用圖像 As Bitmap
        Private _圖檔名稱 As String = "_" & _現用圖案ID.ToString
        Private _圖檔映像 As Bitmap = CType(My.Resources.ResourceManager.GetObject(_圖檔名稱), Bitmap)
        Private _擷取大小 As Size = New Size(_圖檔映像.Height, _圖檔映像.Height)
        Private _畫格總數 As Integer = _圖檔映像.Width \ _圖檔映像.Height
        Private _當下畫格 As Integer = 0
        Public Shadows Event 圖像更新了(ByVal sender As Object, ByVal e As Bitmap) '---傳回呼叫端的事件---
    #End Region
    


  8. 編輯階段的擷圖:

    image
     
  9. 表單的程式碼就更簡化了:

    
    
    
        <System.Runtime.InteropServices.DllImportAttribute("user32.dll")> _
        Private Shared Function DestroyIcon(ByVal handle As IntPtr) As Boolean
        End Function
    
        Private Sub i_圖像更新了(sender As Object, e As System.Drawing.Bitmap) Handles i.圖像更新了
            Dim HIcon As IntPtr = e.GetHicon()
            Dim newIcon As Icon = System.Drawing.Icon.FromHandle(HIcon)
            Me.Icon = newIcon
            DestroyIcon(newIcon.Handle)
        End Sub
    

  10. 效果影片(表單放了多個控制項,並選其一為 Icon):


     
  11. 專案原始碼下載。[]

ku3