Auteur de questions
VB2010 – Problème avec la méthode OnPaint d’un contrôle

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
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
-
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 SubPar 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
-
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