Usercontrol type bouton on/off

Description

c'est un usercontrole composé d'un bouton et d'un label (comme un bouton normal quoi), sauf qu'il connait deux états, ON (bouton reste enfoncé/sunken) et OFF (bouton reste sorti/raised).

Il connait les propriétées suivantes:
- CaptionOFF (texte du bouton à l'état sorti)
- CaptionON (texte du bouton à l'état enfoncé)
- FireEventAfterChange (détermine si une évènement est lancé lorsque l'état du bouton est changé par du code)
- Look (2 états LookON ou LookOFF, peut être changé lors du design ou par code, avec/sans génération de l'évènement)

Il connait 2 évènements:
- ChangedToOn (envoyé après que l'utilisateur ait cliqué dessus et que le bouton devienne enfoncé)
- ChangedToOff (envoyé après que l'utilisateur ait cliqué dessus et que le bouton devienne sorti)

C'est pas très complexe, mais cela m'a été utile lors d'un projet, il montre:
- création complète d'un simple usercontrol
- comment générer des évèements
- utilisation de l'api DrawEdge
- utilisation d'un enum pour le choix de la propriété look du controle
- comment center un label sur bouton (représenté ici par le usercontrol)
- initialisation, sauvegarde et rappel des propriétés d'un usercontrol lors du design

Source / Exemple :


Option Explicit

' évènement lorsque l'utilisateur clique dessus et que le bouton devienne ON/enfoncé
Public Event ChangedToOn()
' évènement lorsque l'utilisateur clique dessus et que le bouton devienne OFF/sorti
Public Event ChangedToOff()

' structure qui tient l'aire du usercontrol (pour le repaint et le centrage du label)
Private m_ClientRec As RECT
' variable interne de la propriété - Texte lorsque le bouton est ON/enfoncé
Private m_CaptionON As String
' variable interne de la propriété - Texte lorsque le bouton est OFF/sorti
Private m_CaptionOFF As String
' variable interne de la propriété - état actuel du bouton
Private m_Look As LookType
' variable interne de la propriété - lancer un évènement lorsque l'état du bouton change par programmation
'                                    l'évènement est toujours généré lorsque l'utilisateur clique dessus
Private m_FireEventAfterChangeLook

' enum de la propriété look du controle (la propriété se présente comme combobox)
Public Enum LookType
    LookOff = 0
    LookOn = 1
End Enum

' declarations Windows API
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Const BDR_RAISEDINNER = &H4 Or &H1
Private Const BDR_SUNKENOUTER = &H2 Or &H8
Private Const BF_RECT = &HF

Private Declare Function DrawEdge Lib "user32" (ByVal hdc As Long, _
                                                qrc As RECT, _
                                                ByVal edge As Long, _
                                                ByVal grfFlags As Long) As Long

Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
     
Private Sub lblCaption_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
    ' si l'utilisateur clique sur le label
    If Button = vbLeftButton Then
        ' changer l'apparance du bouton ON <-> OFF
        If m_Look = LookOff Then
            m_Look = LookOn
        Else
            m_Look = LookOff
        End If
        ' redessiner le controle
        UserControl_Paint
        If m_Look = LookOn Then
            ' le bouton devient ON, lancer l'évènement
            RaiseEvent ChangedToOn
        Else
            ' le bouton devient OFF, lancer l'évènement
            RaiseEvent ChangedToOff
        End If
    End If
End Sub

Private Sub UserControl_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
    ' si l'utilisateur clique sur le usercontrol
    If Button = vbLeftButton Then
        ' changer l'apparance du bouton ON <-> OFF
        If m_Look = LookOff Then
            m_Look = LookOn
        Else
            m_Look = LookOff
        End If
        ' redessiner le controle
        UserControl_Paint
        If m_Look = LookOn Then
            ' le bouton devient ON, lancer l'évènement
            RaiseEvent ChangedToOn
        Else
            ' le bouton devient OFF, lancer l'évènement
            RaiseEvent ChangedToOff
        End If
    End If
End Sub

Private Sub UserControl_Resize()
    ' le contrôle change de taille (par programmation ou lors du design)
    ' lire les nouvelles dimensions du contrôle
    GetWindowRect UserControl.hwnd, m_ClientRec
    ' transformation des coordinés écran vers coordinés client
    With m_ClientRec
        .Right = .Right - .Left
        .Bottom = .Bottom - .Top
        .Left = 0
        .Top = 0
    End With
    ' redessiner le controle
    UserControl_Paint
End Sub

Private Sub UserControl_Paint()
    If Not UserControl.Ambient.UserMode Then
        ' permet d'insérer du code exécuté lors du design time
    Else
        ' permet d'insérer du code exécuté lors du run time
    End If
    UserControl.Cls
    If m_Look = LookOff Then
        ' changer le libellé du contrôle
        lblCaption.Caption = m_CaptionOFF
        ' redessiner les bords sortis
        DrawEdge UserControl.hdc, m_ClientRec, BDR_RAISEDINNER, BF_RECT
    Else
        ' changer le libellé du contrôle
        lblCaption.Caption = m_CaptionON
        ' redessiner les bords enfoncés
        DrawEdge UserControl.hdc, m_ClientRec, BDR_SUNKENOUTER, BF_RECT
    End If
    ' centrer le label sur le bouton/usercontrol
    lblCaption.Top = (((m_ClientRec.Bottom - m_ClientRec.Top) * Screen.TwipsPerPixelY) - lblCaption.Height) / 2
    lblCaption.Left = (((m_ClientRec.Right - m_ClientRec.Left) * Screen.TwipsPerPixelX) - lblCaption.Width) / 2
End Sub

Property Let CaptionOFF(c As String)
    ' exécuté lorsque le propriété est changée (run time et design time)
    m_CaptionOFF = c
    UserControl.Refresh
End Property

Property Get CaptionOFF() As String
    ' exécuté lorsque quelq'un demande le contenu de la propriété
    CaptionOFF = m_CaptionOFF
End Property

Property Let CaptionON(c As String)
    ' exécuté lorsque le propriété est changée (run time et design time)
    m_CaptionON = c
    UserControl.Refresh
End Property

Property Get CaptionON() As String
    ' exécuté lorsque quelq'un demande le contenu de la propriété
    CaptionON = m_CaptionON
End Property

Property Let Look(l As LookType)
    ' exécuté lorsque le propriété est changée (run time et design time)
    m_Look = l
    If m_FireEventAfterChangeLook Then
        ' lancer l'évènement que si la propriété 'FireEventAfterChangeLook' est vraie
        ' cela peut être le cas lors du design ou d'un changement par code
        If m_Look = LookOn Then
            RaiseEvent ChangedToOn
        Else
            RaiseEvent ChangedToOff
        End If
    End If
    UserControl.Refresh
End Property

Property Get Look() As LookType
    ' exécuté lorsque quelq'un demande le contenu de la propriété
    Look = m_Look
End Property

Property Let FireEventAfterChangeLook(f As Boolean)
    ' exécuté lorsque le propriété est changée (run time et design time)
    ' définit si le changement le l'état (effectué lors du design ou par code,
    ' pas par l'évènement clic) lance l'évènement ChangedToOn ou ChangedToOff
    m_FireEventAfterChangeLook = f
End Property

Property Get FireEventAfterChangeLook() As Boolean
    ' exécuté lorsque quelq'un demande le contenu de la propriété
    FireEventAfterChangeLook = m_FireEventAfterChangeLook
End Property

Private Sub UserControl_InitProperties()
    ' initialisation des propriétés lorsque le contrôle est mis sur un form
    m_CaptionOFF = "Caption_OFF"
    m_CaptionON = "Caption_ON"
    m_Look = LookOff
    m_FireEventAfterChangeLook = False
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    ' permet de récupérer le dernier état des propriétés lors du design et lors du lancement du code
    m_CaptionOFF = PropBag.ReadProperty("CaptionOFF", "Caption_OFF")
    m_CaptionON = PropBag.ReadProperty("CaptionON", "Caption_ON")
    m_Look = PropBag.ReadProperty("Look", LookOff)
    m_FireEventAfterChangeLook = PropBag.ReadProperty("FireEventAfterChangeLook", False)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    ' permet de sauver le dernier état des propriétés lors du design
    PropBag.WriteProperty "CaptionOFF", m_CaptionOFF, "Caption_OFF"
    PropBag.WriteProperty "CaptionON", m_CaptionON, "Caption_ON"
    PropBag.WriteProperty "Look", m_Look, LookOff
    PropBag.WriteProperty "FireEventAfterChangeLook", m_FireEventAfterChangeLook, False
End Sub

Conclusion :


Il suffit d'ajouter cmdOnOff.ctl au projet (préférable à du copier/coller du code car dans ce cas il faut encore y ajouter le label), il va se rajouter à la barre des controles. Depuis là, mettez le sur un form et éditez ses propriétés.

J'ai cherché un peu sur le web, mais je n'ai rien trouvé de finalisé et utilisable, donc j'ai consacré 2 heures à en faire un moi même. Il est encore pensable de l'étendre avec une image, mais à vous de la faire ...

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.