Fond de feuille animé : dégradé mouvant pour about ou splashscreen


Description

Hello tout le monde,
hier je m'amusait à chercher comment rendre mes moches applis un peu plus attractives, et je me suis renseigné sur les dégradés gerés par le framework .net (merci Richard Clark).
C'est en bidouillant un peu avec que je suis arrivé à ce resultat assez simpa. Des degradés mouvants!
Vous spécifiez deux couleur et un type de degradé, et la classe se charge de redessiner en permance la feuille.
Le plus interessant est je pense, celui en "diagonale", mais les verticaux et horizontaux font aussi leur petit effet.
J'ai donc tenter de rendre mon code générique en écrivant une petit classe très simple à utiliser.
La méthode en elle même est, comme je l'ai dit, une bidouille.
En effet, je ne travaille pas sur le fond de la feuille, mais sur un label de la taille de la feuille, ajouté en arrière plan.
Ceci du fait qu'en travaillant sur la feuille elle même, le form_paint est appelé en permanence, et produit un clignottement très désagréable.

Enfin, je precise dans le titre "pour about ou splashscreen", car ce petit effet de cowboy est gourmand en ressources,
à eviter donc sur une vraie appli ^^

Deux classes donc ici, la première, destiné à mettre en fond une image dégradé sur un control, et l'autre qui se charge de l'effet mouvant.
J'ai également mis un petit sample dans le zip.

Have fun

Source / Exemple :


'classe de dessin de degradés sur un controle

Public Class HbCtrlDegrad

    Public Enum TypeDegrad
        Horizontal
        Vertical
        Diagonale_avant
        Diagonale_arriere
    End Enum

    Friend Shared Sub Degrade(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal type As TypeDegrad)
        Degrade(ctrl, startcolor, endcolor, type, 0)
    End Sub

    Friend Shared Sub Degrade(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal angle As Single)
        Degrade(ctrl, startcolor, endcolor, 5, angle)
    End Sub

    Friend Shared Sub Degrade(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal type As TypeDegrad, ByVal angle As Single, Optional ByVal width As Integer = -1, Optional ByVal height As Integer = -1)
        If width = -1 Then width = ctrl.Width
        If height = -1 Then height = ctrl.Height
        Dim a As Image = New Bitmap(ctrl.Width, ctrl.Height)
        Dim bgGraph As Graphics = Graphics.FromImage(a)
        Dim rect As New Rectangle(New Point(0, 0), New Point(width, height))
        Dim degradbrush As Drawing2D.LinearGradientBrush
        Select Case type
            Case TypeDegrad.Horizontal
                degradbrush = New Drawing2D.LinearGradientBrush(rect, startcolor, endcolor, Drawing2D.LinearGradientMode.Horizontal)
            Case TypeDegrad.Vertical
                degradbrush = New Drawing2D.LinearGradientBrush(rect, startcolor, endcolor, Drawing2D.LinearGradientMode.Vertical)
            Case TypeDegrad.Diagonale_avant
                degradbrush = New Drawing2D.LinearGradientBrush(rect, startcolor, endcolor, Drawing2D.LinearGradientMode.ForwardDiagonal)
            Case TypeDegrad.Diagonale_arriere
                degradbrush = New Drawing2D.LinearGradientBrush(rect, startcolor, endcolor, Drawing2D.LinearGradientMode.BackwardDiagonal)
            Case Else
                degradbrush = New Drawing2D.LinearGradientBrush(rect, startcolor, endcolor, angle, True)
        End Select
        bgGraph.FillRectangle(degradbrush, rect)
        ctrl.BackgroundImage = a
    End Sub

End Class

'classe de gestion de fond mouvant 

Public Class RollingBG

    Private b As Boolean
    Private _interval As Integer
    Private _startcolor As Color
    Private _endcolor As Color
    Private _curform As Form
    Private _backlabel As Label = New Label
    Private _angle As Single
    Private thread1 As Threading.Thread

    Public Enum TypeDegrad
        Horizontal
        Vertical
        Diagonale
    End Enum

    Private Delegate Sub DelegateAddLabel(ByVal newlabel As Label)
    Private Delegate Sub DelegateRemoveLabel(ByVal newlabel As Label)
    Private Delegate Sub DelegateChangeBGColor(ByVal clr As Color)
    Private Delegate Sub DelegateDegrade(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal angle As Single)
    Private Delegate Sub DelegateDegradeHV(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal type As TypeDegrad, ByVal angle As Single, ByVal width As Integer, ByVal height As Integer)

    Public Sub New()
        _interval = 10
    End Sub

    Public Sub New(ByVal interval As Integer)
        If interval > 0 Then
            _interval = interval
        Else
            _interval = 10
        End If
    End Sub

    Private Function newlabel(ByVal width As Single, ByVal height As Single) As Label
        Dim newlbl As New Label
        newlbl.Width = width
        newlbl.Height = height
        Return newlbl
    End Function

    Public Sub vertical(ByRef curform As Form, ByVal startcolor As Color, ByVal endcolor As Color)
        start(curform, startcolor, endcolor, 2)
    End Sub

    Public Sub horizontal(ByRef curform As Form, ByVal startcolor As Color, ByVal endcolor As Color)
        start(curform, startcolor, endcolor, 1)
    End Sub

    Public Sub diagonal(ByRef curform As Form, ByVal startcolor As Color, ByVal endcolor As Color)
        start(curform, startcolor, endcolor, 0)
    End Sub

    Private Sub start(ByRef curform As Form, ByVal startcolor As Color, ByVal endcolor As Color, ByVal type As Integer)
        pause()
        Select Case type
            Case 0
                thread1 = New Threading.Thread(AddressOf diagonal_thread)
            Case 1
                thread1 = New Threading.Thread(AddressOf horizontal_thread)
            Case 2
                thread1 = New Threading.Thread(AddressOf vertical_thread)
        End Select
        'pause()
        b = True
        _curform = curform
        _startcolor = startcolor
        _endcolor = endcolor
        AddHandler _curform.FormClosing, AddressOf FormClosing
        thread1.Start()
    End Sub

    Private Sub vertical_thread()
        Dim descendant As Boolean = True
        Dim i As Integer = 1
        Dim max As Integer = _curform.Height + (_curform.Height / 4)
        _curform.Invoke(New DelegateChangeBGColor(AddressOf changeBGcolor), New Object() {_endcolor})
        _backlabel = newlabel(_curform.Width, _curform.Height)
        _curform.Invoke(New DelegateAddLabel(AddressOf addlabel), New Object() {_backlabel})
        Do While b = True
            Do While (i < max) And (i >= 1)
                If b = False Then Exit Do
                _backlabel.Invoke(New DelegateDegradeHV(AddressOf DegradeA), New Object() {_backlabel, _startcolor, _endcolor, TypeDegrad.Vertical, 0, -1, i})
                Threading.Thread.Sleep(_interval)
                If descendant = True Then i += 1 Else i -= 1
            Loop
            descendant = Not descendant
            If descendant = False Then i -= 1 Else i += 1
        Loop
        _curform.Invoke(New DelegateRemoveLabel(AddressOf removelabel), New Object() {_backlabel})
    End Sub

    Private Sub horizontal_thread()
        Dim descendant As Boolean = True
        Dim i As Integer = 1
        Dim max As Integer = _curform.Width + (_curform.Width / 4)
        _curform.Invoke(New DelegateChangeBGColor(AddressOf changeBGcolor), New Object() {_endcolor})
        _backlabel = newlabel(_curform.Width, _curform.Height)
        _curform.Invoke(New DelegateAddLabel(AddressOf addlabel), New Object() {_backlabel})
        Do While b = True
            Do While (i < max) And (i >= 1)
                If b = False Then Exit Do
                _backlabel.Invoke(New DelegateDegradeHV(AddressOf DegradeA), New Object() {_backlabel, _startcolor, _endcolor, TypeDegrad.Horizontal, 0, i, -1})
                Threading.Thread.Sleep(_interval)
                If descendant = True Then i += 1 Else i -= 1
            Loop
            descendant = Not descendant
            If descendant = False Then i -= 1 Else i += 1
        Loop
        _curform.Invoke(New DelegateRemoveLabel(AddressOf removelabel), New Object() {_backlabel})

    End Sub

    Private Sub diagonal_thread()
        _backlabel = newlabel(_curform.Width, _curform.Height)
        _curform.Invoke(New DelegateAddLabel(AddressOf addlabel), New Object() {_backlabel})
        Do While b
            For i As Integer = 1 To 360
                If b = False Then Exit For
                If i Mod 90 = 0 Then i = i + 1 'evite le clignottement des angles "droits" (90,180,270)
                _backlabel.Invoke(New DelegateDegrade(AddressOf DegradeB), New Object() {CType(_backlabel, Control), _startcolor, _endcolor, i})
                Threading.Thread.Sleep(_interval)
            Next
        Loop
        _curform.Invoke(New DelegateRemoveLabel(AddressOf removelabel), New Object() {_backlabel})
    End Sub

    'event ajouté à la form 
    Private Sub FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
        pause()
    End Sub

    Public Sub pause()
        b = False
        If Not IsNothing(thread1) Then
            thread1.Abort()
            removelabel(_backlabel)
        End If
    End Sub

    'Sub deleguées
    Private Sub addlabel(ByVal newlabel As Label)
        _curform.Controls.Add(newlabel)
    End Sub

    Private Sub removelabel(ByVal newlabel As Label)
        _curform.Controls.Remove(newlabel)
    End Sub

    Private Sub changeBGcolor(ByVal clr As Color)
        _curform.BackColor = clr
    End Sub

    Private Sub DegradeA(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal type As TypeDegrad, ByVal angle As Single, ByVal width As Integer, ByVal height As Integer)
        If b = True Then
            HbCtrlDegrad.Degrade(ctrl, startcolor, endcolor, type, 0, width, height)
        End If
    End Sub

    Private Sub DegradeB(ByRef ctrl As Control, ByVal startcolor As Color, ByVal endcolor As Color, ByVal angle As Single)
        If b = True Then
            HbCtrlDegrad.Degrade(ctrl, startcolor, endcolor, 5, angle)
        End If
    End Sub

End Class

Conclusion :


J'ai presque honte de perdre du temps la dessus, mais bon... ^^'
Je met niveau Initié, même si l'utilisation de la classe est simpliste, et que la partie algorithmique se resume à peu de ligne de code, le fait qu'elle implémente threads et autres delegués necessite je pense, ce niveau 2. Faites le moi savoir si vous pensez que je m'emballe ^^.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.