IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

CustomTextBox avec borderColor [Débutant]


Sujet :

VB.NET

  1. #1
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut CustomTextBox avec borderColor
    Bonjour,

    Toujours pour m'exercer dans mon apprentissage sur les classes, je me suis donné comme exercice la création d'un textbox personnalisé avec une bordure lorsque le contrôle prend le focus.

    J'ia donc besoin de l'event OnGotFocus pour déclencher l'événement.
    Mais pour dessiner le rectangle correspondant à la bordure, je n'ai pas trouvé d'autre moyen que d'utiliser l'event OnPaint.
    Le pb est d'appeler le OnPaint depuis l'event OnGotFocus.

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    Imports System.ComponentModel
     
    Public Class CustomTextBox
        Inherits System.Windows.Forms.TextBox
        Private _GotFocus As Boolean
        Private _BorderColor As Color = Color.Red
        Private _BorderWidth As SByte = 1
     
     
        <Browsable(True), Category("Apparence")> _
        Public Property BorderColor() As Color
            Get
                Return _BorderColor
            End Get
            Set(ByVal value As Color)
                _BorderColor = value
            End Set
        End Property
     
        <Browsable(True), Category("Apparence")> _
        Public Property BorderWidth() As SByte
            Get
                Return _BorderWidth
            End Get
            Set(ByVal value As SByte)
                _BorderWidth = value
            End Set
        End Property
     
     
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
            MyBase.BorderStyle = Windows.Forms.BorderStyle.FixedSingle
            If _GotFocus Then
                Dim mypen As Pen
                mypen = New Pen(_BorderColor, _BorderWidth)
                e.Graphics.DrawRectangle(mypen, _BorderWidth, _BorderWidth, Me.Width - 2 * _BorderWidth, Me.Height - 2 * _BorderWidth)
            End If
        End Sub
     
        Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
            MyBase.OnGotFocus(e)
            _GotFocus = True
            '... ici : comment appeler OnPaint ???
        End Sub
     
        Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
            MyBase.OnLostFocus(e)
            _GotFocus = False
        End Sub
    End Class

    D'abord : La "philosophie" est-elle la bonne ?

    Si oui, comment appeler la procédure OnPaint depuis OnGotFocus.

    J'espère que cet exemple est aussi simple que je l'imagine, sinon merci de me le dire, je passerais à un exercice plus facile !!

  2. #2
    Membre très actif
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 267
    Par défaut
    bonjour, as-tu essayer ceci :

  3. #3
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    ça ne peut pas marcher : le e de GotFocus est de type EventArgs tandis que celui de OnPaint est de type PaintEventArgs

  4. #4
    Membre très actif
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 267
    Par défaut
    ok, essaye ceci :

  5. #5
    Modérateur
    Avatar de Sankasssss
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 842
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 842
    Par défaut
    Bonsoir,

    appel Me.Invalidate() pour repeindre le composant.

    http://msdn.microsoft.com/fr-fr/libr...(v=vs.90).aspx

  6. #6
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    Citation Envoyé par Sankasssss Voir le message
    Bonsoir,

    appel Me.Invalidate() pour repeindre le composant.
    à quel endroit ?

    ok, essaye ceci :


    Marche pas, il faut un argument de type PaintEventArgs

    ...

    De toute façon, j'ai fait un test : la procédure OnPaint n'est jamais lue. Donc avant de savoir comment passer de OnGotFocus à OnPaint, il faudrait déjà comprendre comment aller dans OnPaint. Le code suivant, qui aurait pour effet de tracer une bordure rouge, indépendamment de tout événement, ne marche donc pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    Imports System.ComponentModel
     
    Public Class CustomTextBox
        Inherits System.Windows.Forms.TextBox
        Private _GotFocus As Boolean
        Private _BorderColor As Color = Color.Red
        Private _BorderWidth As SByte = 3
     
     
        <Browsable(True), Category("Apparence")> _
        Public Property BorderColor() As Color
            Get
                Return _BorderColor
            End Get
            Set(ByVal value As Color)
                _BorderColor = value
                Me.Invalidate()
            End Set
        End Property
     
        <Browsable(True), Category("Apparence")> _
        Public Property BorderWidth() As SByte
            Get
                Return _BorderWidth
            End Get
            Set(ByVal value As SByte)
                _BorderWidth = value
                Me.Invalidate()
            End Set
        End Property
     
     
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
     
            MyBase.BorderStyle = Windows.Forms.BorderStyle.FixedSingle
            Dim mypen As Pen
            mypen = New Pen(_BorderColor, _BorderWidth)
            e.Graphics.DrawRectangle(mypen, e.ClipRectangle)
        End Sub
    End Class

  7. #7
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    Bonsoir,

    Après pas mal de recherches sur internet, j'ai trouvé un article que j'ai fini par parvenir à adapter à mon cas (simplifié) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    Imports System
    Imports System.Drawing
    Imports System.Runtime.InteropServices
    Imports System.Windows.Forms
    Imports System.ComponentModel
     
    Public Class TextBoxWithBorder
        Inherits System.Windows.Forms.TextBox
     
        Private _couleur As Color = Color.Red
        Private Const WM_PAINT As Integer = 15
     
        Declare Auto Function GetWindowDC Lib "user32.dll" Alias "GetWindowDC" (ByVal hWnd As IntPtr) As IntPtr
     
        Public Property BorderColor() As Color
            Get
                Return _couleur
            End Get
            Set(ByVal Value As Color)
                Me._couleur = Value
                Me.Invalidate()
            End Set
        End Property
     
        Protected Overloads Overrides Sub WndProc(ByRef m As Message)
            Select Case m.Msg
                Case WM_PAINT
                    MyBase.WndProc(m)
                    OnPaint()
                Case Else
                    MyBase.WndProc(m)
            End Select
        End Sub
     
        Protected Overloads Sub OnPaint()
            Dim rcItem As Rectangle = New Rectangle(0, 0, Me.Width - 1, Me.Height - 1)
            Dim hDC As IntPtr = GetWindowDC(Me.Handle)
            Dim gfx As Graphics = Graphics.FromHdc(hDC)
            Dim mypen As Pen = New Pen(_couleur, 1)
            gfx.DrawRectangle(mypen, rcItem)
            gfx.Dispose()
        End Sub
     
    ' et pour s'amuser un peu, une procédure événementielle pour que la couleur de la bordure
    ' change lorsque le contrôle reçoit le focus 
     
    Private Sub TextBoxWithBorder_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.GotFocus
            _oldcolor = _bordercolor
            _oldwidth = _penWidth
            _penWidth = _penWidthwhenfocus
            _bordercolor = _bordorcolorwhenfocus
        End Sub
     
        Private Sub TextBoxWithBorder_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.LostFocus
            _bordercolor = _oldcolor
            _penWidth = _oldwidth
            OnPaint()
        End Sub
    End Class
    MAIS ...

    Bien que le lien explique comment le code a été construit je reste sur ma faim. Autant cela m'a permis, par "imitation", de parvenir à mes fins, autant je serais incapable d'étendre le principe posé (l'appel à l'API windows user32.dll) à d'autres cas.

    Je me pose des tas de questions,

    - comment peut-on savoir qu'il faut faire appel à une API Windows ou pas pour faire une classe personnalisée ? Comment le développeur a-t-il su ? Par exemple comment savoir que pour dessiner une bordure à un textbox, il faut invoquer une API windows, alors que pour un bouton, une simple procédure OnPaint suffit (cf tuto de P.LASSERRE page 865 dont je m'étais inspiré pour mon code initial) ?
    - comment savoir comment utiliser cette API pour le besoin précis qui est le nôtre lorsque nous développons une classe ? Par exemple il est question à un moment donné d'une constante WM_PAINT = 15. D'où cela vient-il ?
    - le recours à l'API windows était-elle vraiment incontournable ?

    Bref, j'ai su créer un code simple permettant de créer une bordure sur un textbox, mais cela ne veut pas dire que je saurai le faire sur un autre contrôle demain tant que je n'aurais pas réponses à ces interrogations.

    En clair, malgré les explications du tuto ci-dessus, c'est presque comme si on m'avait donné la DLL toute faite.

  8. #8
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    En illustration de mes questions, on pourrait penser que le code du post précédent pourrait s'appliquer tel quel à n'importe quel contrôle de formulaire en modifiant seulement la ligne 8. Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Inherits System.Windows.Forms.ComboBox
    pour appliquer la même fonction à un combobox.

    Or, il n'en est rien. La procédure événementielle Gotfocus ne marche pas (bien que le code la pénètre bien, après vérification).

    Cela veut dire qu'il faut encore trouver une autre logique.

    Ce qui est surprenant, c'est que si je supprime la procédure gotfocus de la classe et que je "l'externalise" dans la class du formulaire sous le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        Private Sub TextBoxWithBorder1_GotFocus(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxWithBorder1.GotFocus
            Dim _oldcolor As Color = Me.TextBoxWithBorder1.BorderColor
            Dim _oldwidth As SByte = Me.TextBoxWithBorder1.BorderWidth
            Me.TextBoxWithBorder1.BorderWidth = Me.TextBoxWithBorder1.BorderWidthOnFocus
            Me.TextBoxWithBorder1.BorderColor = Me.TextBoxWithBorder1.BorderColorOnFocus
        End Sub
    alors ça marche très bien. Mais ce n'est pas pareil du point de vue programmatique et cela fait perdre tout son intérêt à la création d'une classe pour customiser un contrôle WinForms

  9. #9
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    Bon je m'en suis sorti un rajouter un appel à OnPaint comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Private Sub TextBoxWithBorder_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.GotFocus
            _oldcolor = _bordercolor
            _oldwidth = _penWidth
            _penWidth = _penWidthwhenfocus
            _bordercolor = _bordorcolorwhenfocus
            OnPaint()
        End Sub
     
        Private Sub TextBoxWithBorder_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.LostFocus
            _bordercolor = _oldcolor
            _penWidth = _oldwidth
            OnPaint()
            Me.Invalidate()
        End Sub
    Maintenant mon code marche à la fois pour un TextBox et un ComboBox.

    Mais il faut trouver un "inherits" qui englobe ces 2 contrôles.
    Or Combobox hérite de System.Windows.Controls d'après MSDN mais l'intruction Inherits System.Windows.Controls" n'est pas acceptée.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. requete avec OBCD et visual c++
    Par Anonymous dans le forum MFC
    Réponses: 12
    Dernier message: 18/11/2004, 16h15
  2. [langage] Comparer Perl avec d'autres langages comme C ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 10/08/2002, 23h52
  3. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10
  4. [Kylix] Runtime error 230 avec INDY
    Par Anonymous dans le forum EDI
    Réponses: 2
    Dernier message: 23/03/2002, 11h51
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo