none
VB2010 – Problème avec la méthode OnPaint d’un contrôle RRS feed

  • Question

  • Bonjour à tous,

    Au chapitre « Peinture et rendu personnalisés des contrôles » et à la rubrique «Contrôles dessinés par l'utilisateur » de l’aide de Visual Basic 2010, il est dit que pour modifier l’apparence graphique d’un contrôle il fallait substituer la méthode OnPaint de la classe de base par une expression du type :

        Protected Overrides Sub OnPaint(pevent As System.Windows.Forms.PaintEventArgs)

            MyBase.OnPaint(pevent)

           

        End Sub

    Tout cela semble simple mais si j’applique cette procédure à un contrôle « Button », voici ce qui arrive :

    -         En premier lieu le bouton n’a subi aucune transformation graphique, c’est le bouton original auquel je voudrais soustraire l’interface graphique d’origine pour la remplacer par une de mon choix.

    -         En second lieu j’ai appliqué une modification graphique à l’apparence du bouton en suivant la procédure indiquée ci-dessus, mais je constate que l’interface graphique d’origine est toujours présente alors que je pensais que celle-ci serait remplacée par la nouvelle ! Qu’ai-je mal interprété dans ce processus ?

    -         Enfin, en dernier lieu le bouton ainsi modifié ne se redessine pas après un redimensionnement du formulaire. Là aussi je pensais que ce processus était automatique. Peut-être est-ce lié au problème précédemment rencontré ?

    Voilà, si une personne connait une solution ou bien avait une lecture à me conseiller je lui en serais gré. Merci d’avance

       Voici le code que j’ai tapé pour obtenir ces résultats :

    Public Class Form1

        Sub New()

            InitializeComponent()

            Me.Text = "Rendu graphique d'un bouton"

            Me.SetBounds(250, 20, 300, 150)

            Me.Cursor = Cursors.Hand

            Me.BackColor = Color.White

            Me.SizeGripStyle = Windows.Forms.SizeGripStyle.Show

            Me.ResizeRedraw = True

            AddHandler Me.MouseDoubleClick, AddressOf Me.Close

            ' Initialisation du bouton

            Dim b As New ButtonWithModifiedUI

            Me.Controls.Add(b)

            b.Size = New Size(150, 100)

            b.Location = New Point(Me.ClientSize.Width / 2 - b.Width / 2, Me.ClientSize.Height / 2 - b.Height / 2)

            b.BackColor = Color.LightGray

            b.Text = "Bouton"

        End Sub

    End Class

    Class ButtonWithModifiedUI

        Inherits Button

        Protected Overrides Sub OnPaint(pevent As System.Windows.Forms.PaintEventArgs)

            MyBase.OnPaint(pevent)

            Call OnPaintButton(pevent)

        End Sub

        Private Sub OnPaintButton(pevent As System.Windows.Forms.PaintEventArgs)

            Dim sf As New StringFormat

            sf.Alignment = StringAlignment.Center

            sf.LineAlignment = StringAlignment.Center

            pevent.Graphics.FillEllipse(Brushes.LightSalmon, pevent.ClipRectangle)

            pevent.ClipRectangle.Inflate(-1, -1)

            pevent.Graphics.DrawEllipse(Pens.Gray, pevent.ClipRectangle)

    pevent.Graphics.DrawString("ButtonWithModifiedUI", New Font("Arial", 10), Brushes.Brown, pevent.ClipRectangle, sf)

        End Sub

    End Class

    Bonnes fêtes de fin d’année à tous

    Cordialement

    SL





    • Modifié Santa Lina mardi 30 décembre 2014 09:56
    mercredi 24 décembre 2014 07:35

Toutes les réponses

  • Bonjour à tous,

    J’ai trouvé une solution. Il fallait non pas hériter de la classe « Button » mais de la classe « Control ». Néanmoins un problème de rafraichissement existe toujours lorsque je redimensionne le formulaire ! Si une personne peut me donner son avis, je lui en serais gré et la remercie par avance.

    Voici le code du bouton personnalisé ainsi modifié.

    Imports System.Drawing.Drawing2D

    Public Class Form1

        Sub New()

            InitializeComponent()

            Me.Text = "Rendu graphique d'un bouton"

            Me.SetBounds(250, 20, 300, 150)

            Me.Cursor = Cursors.Hand

            Me.BackColor = Color.White

            Me.SizeGripStyle = Windows.Forms.SizeGripStyle.Show

            Me.ResizeRedraw = True

            Me.DoubleBuffered = True

            AddHandler Me.MouseDoubleClick, AddressOf Me.Close

            ' Initialisation du bouton

            Dim b As New ButtonWithModifiedUI

            Me.Controls.Add(b)

            b.Size = New Size(150, 100)

            b.Location = New Point(Me.ClientSize.Width / 2 - b.Width / 2, Me.ClientSize.Height / 2 - b.Height / 2)

            ' Découpe du bouton à la forme souhaitée

            ' pour ne pas afficher une forme grisée rectangulaire

            Dim gp As New GraphicsPath

            gp.AddEllipse(b.ClientRectangle)

            b.Region = New Region(gp)

            ' N'est pas nécessaire

            ' car la surface grisée n'apparaît plus après la découpe

            'b.BackColor = Me.BackColor

        End Sub

        Private Sub Form1_Resize(sender As Object, e As System.EventArgs) Handles Me.Resize

            ' Redessine le boutton

            ' Non implémenté pour le moment

            'Beep()

        End Sub

    End Class

    Friend Class ButtonWithModifiedUI

        Inherits Control

        Protected Overrides Sub OnPaint(pevent As System.Windows.Forms.PaintEventArgs)

            MyBase.OnPaint(pevent)

            Call OnPaintButton(pevent)

        End Sub

        Friend Sub OnPaintButton(pevent As System.Windows.Forms.PaintEventArgs)

            Dim sf As New StringFormat

            sf.Alignment = StringAlignment.Center

            sf.LineAlignment = StringAlignment.Center

            Dim ButtonColor As Brush = Brushes.Chartreuse

            Dim Rc As Rectangle = pevent.ClipRectangle

            Rc.Inflate(-2, -2)

            pevent.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            If IsMouseDown Then

                Rc.Inflate(-1, -1)

                pevent.Graphics.FillEllipse(ButtonColor, Rc)

                pevent.Graphics.DrawEllipse(Pens.Gray, Rc)

                Rc.Inflate(-1, -1)

                pevent.Graphics.DrawEllipse(Pens.Gray, Rc)

            Else

                Rc.Inflate(-1, -1)

                pevent.Graphics.DrawEllipse(Pens.Gray, Rc)

                Rc.Offset(1, 1)

                pevent.Graphics.DrawEllipse(New Pen(Brushes.Gray, 2), Rc)

                Rc.Offset(-1, -1)

                pevent.Graphics.FillEllipse(ButtonColor, Rc)

            End If

            pevent.Graphics.DrawString("ButtonWithModifiedUI", New Font("Arial", 9), Brushes.Black, Rc, sf)

        End Sub

        Dim IsMouseDown As Boolean

        Private Sub ButtonWithModifiedUI_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown

            If Not e.Button = Windows.Forms.MouseButtons.Left Then Exit Sub

            IsMouseDown = True

            IsMouseUp = False

            Invalidate()

        End Sub

        Dim IsMouseUp As Boolean

        Private Sub ButtonWithModifiedUI_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

            If Not e.Button = Windows.Forms.MouseButtons.Left Then Exit Sub

            IsMouseDown = False

            IsMouseUp = True

            Invalidate()

        End Sub

    End Class

    Bonne fête de fin d’année

    Cordialement

    SL

    mardi 30 décembre 2014 09:58
  • Bonjour à tous,

    Pour résoudre le problème de distorsion de l’image du bouton, j’ai créé un délégué avec une méthode Invoke pour appeler la méthode OnPaint du Control. Mais je rencontre un problème au niveau de l’initialisation de l’objet PaintEventArgs, celui-ci prend deux arguments obligatoires qui sont en lecture seule et je n’ai pas trouvé la méthode pour programmer ces arguments ! Peut-être que cette méthode n’est pas la bonne ?

    Voici l’erreur telle qu’elle se présente :

    Voici le code du processus:

       Delegate Sub OnPaintDelegate(ByVal e As PaintEventArgs)

        Private Sub Form1_Resize(sender As Object, e As System.EventArgs) Handles Me.Resize

            ' Redessine le boutton

            Dim fr As New OnPaintDelegate(AddressOf b.OnPaintButton)

            Dim pe As New PaintEventArgs  With {.Graphics  , .clipRect  }

            fr.Invoke(pe)

    End Sub

    Par ailleurs, j’ai remarqué que lors du survol du bouton par une autre fenêtre celui-ci n’était pas redessiné. Comment corriger ce problème ?

    Par avance je remercie toutes les personnes qui pourront me donner leur avis.

    Bonne fête de fin d’année

    Cordialement

    SL


    • Modifié Santa Lina mercredi 31 décembre 2014 12:45
    mercredi 31 décembre 2014 12:41
  • Voici la solution trouvée par Richard Clark, elle fonctionne 10/10.

    Bonne lecture

    Imports System.Drawing.Drawing2D

    Public Class Form1

        Dim cb As New CustomButton

        Sub New()

            InitializeComponent()

            Me.Text = "Bouton personnalisé"

            Me.StartPosition = FormStartPosition.CenterScreen

            Me.SetClientSizeCore(300, 150)

            Me.BackColor = Color.White

            Me.SizeGripStyle = Windows.Forms.SizeGripStyle.Show

            AddHandler Me.MouseDoubleClick, AddressOf Me.Close

            Me.Controls.Add(cb)

        End Sub

    End Class

    Friend Class CustomButton

        Inherits Control

        Dim gp As New GraphicsPath

        Dim sf As New StringFormat

        Sub New()

            MyBase.New()

            sf.Alignment = StringAlignment.Center

            sf.LineAlignment = StringAlignment.Center

            Me.Size = New Size(100, 100)

            Me.Location = New Point(100, 15)

            Me.Cursor = Cursors.Hand

            Me.DoubleBuffered = True

            gp.AddEllipse(Me.ClientRectangle)

            Me.Region = New Region(gp)

        End Sub

        Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)

            MyBase.OnPaint(e)

            Call OnPaintButton(e)

        End Sub

        Friend Sub OnPaintButton(e As System.Windows.Forms.PaintEventArgs)

            Dim ButtonColor As Brush = Brushes.Chartreuse

            ' Cette instruction n'est pas valide car elle ne redessine pas le bouton correctement

            'Dim Rc As Rectangle = e.ClipRectangle 

            Dim Rc As Rectangle = New Rectangle()

            Rc.Width = Me.Width

            Rc.Height = Me.Height

            Rc.Inflate(-2, -2)

            e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            If IsMouseDown Then

                Rc.Inflate(-1, -1)

                e.Graphics.FillEllipse(ButtonColor, Rc)

                e.Graphics.DrawEllipse(Pens.Gray, Rc)

                Rc.Inflate(-1, -1)

                e.Graphics.DrawEllipse(Pens.Gray, Rc)

            Else

                Rc.Inflate(-1, -1)

                e.Graphics.DrawEllipse(Pens.Gray, Rc)

                Rc.Offset(1, 1)

                e.Graphics.DrawEllipse(New Pen(Brushes.Gray, 2), Rc)

                Rc.Offset(-1, -1)

                e.Graphics.FillEllipse(ButtonColor, Rc)

            End If

            e.Graphics.DrawString("CustomButton", New Font("Arial", 9), Brushes.Black, Rc, sf)

        End Sub

        Dim IsMouseDown As Boolean

        Private Sub CustomButton_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown

            If Not e.Button = Windows.Forms.MouseButtons.Left Then Exit Sub

            IsMouseDown = True

            IsMouseUp = False

            Invalidate()

        End Sub

        Dim IsMouseUp As Boolean

        Private Sub CustomButton_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

            If Not e.Button = Windows.Forms.MouseButtons.Left Then Exit Sub

            IsMouseDown = False

            IsMouseUp = True

            Invalidate()

        End Sub

        Private Sub CustomButton_MouseClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick

            Beep()

        End Sub

    End Class

    Bonne année 2015

    Cordialement

    SL

    mardi 6 janvier 2015 11:56