AFFICHER UN TEXTE OU DES RECTANGLES, ELLIPSES, POLYGONES, ETC... INCLINÉS EN VB

cs_bigboss9 Messages postés 162 Date d'inscription jeudi 22 janvier 2004 Statut Membre Dernière intervention 20 juillet 2013 - 10 avril 2010 à 10:07
benji2000 Messages postés 78 Date d'inscription samedi 26 août 2006 Statut Membre Dernière intervention 25 novembre 2016 - 13 nov. 2010 à 15:25
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51583-afficher-un-texte-ou-des-rectangles-ellipses-polygones-etc-inclines-en-vb-2008-2-methodes-possibles

benji2000 Messages postés 78 Date d'inscription samedi 26 août 2006 Statut Membre Dernière intervention 25 novembre 2016
13 nov. 2010 à 15:25
Merci pour ta source, je trouve cette fonction bien simpa =D
Bonne continuation =)
Adn56 Messages postés 1172 Date d'inscription jeudi 24 mai 2007 Statut Membre Dernière intervention 28 septembre 2013 1
21 avril 2010 à 18:09
variables local et d'autres comme les SolidBrush ou les pen.
même si des essais avec ou sans ne change rien aux fuites de mémoire (si cela en sont bien, car je ne sais pas trop)
Voici en premier la procédure paint qui bouff 8Ko/sec et bloque à 12444Ko (avec variables dans la sub)
ensuite en dessous la même qui bouff 4Ko/sec mais qui ne bloque pas ! (avec variables hors de la sub)
regarde si tu y vois quelque chose pour l'expliquer. Bigboss si tu es dans le coin tes conseils nous seront utiles (merci)

1---------------------------------------------------
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

' const de taille (demi control)
Dim X As Integer = CInt(Me.Width / 2)
Dim Y As Integer = CInt(Me.Height / 2)

'Si _CercleHorloge dessine le cercle autour de l'horloge
If _CercleHorloge Then
Dim couleurCercle As New Pen(_couleurCercle, 1)
Dim rect As New Rectangle(2, 2, Me.Width - 3, Me.Height - 3)
e.Graphics.DrawEllipse(couleurCercle, rect)
End If

'heure actuelle et variable de calcul de la position des aiguilles
Dim heure_actuel As DateTime = DateTime.Now
Dim n, z, u, long_x, long_y, arriere_x, arriere_y, epaisseur_haut_x, epaisseur_haut_y, epaisseur_bas_x, epaisseur_bas_y As Single
Dim points_aiguilles(3) As PointF

'-----------------------
' Aiguille des Secondes (si propriété AiguilleSec à true)
If _AiguilleSec Then
n = CSng(heure_actuel.Second * 200 / 60)
z = CSng(n / 100 * PI)
u = CSng((n + 50) / 100 * PI)

long_x = CSng(Math.Sin(z) * 0.9 * X)
long_y = CSng(-Math.Cos(z) * 0.9 * Y)

arriere_x = CSng(-Math.Sin(z)) * 10
arriere_y = CSng(Math.Cos(z)) * 10

epaisseur_haut_x = CSng(Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_haut_y = CSng(-Math.Cos(u)) * _EpaisseurAiguilles

epaisseur_bas_x = CSng(-Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_bas_y = CSng(Math.Cos(u)) * _EpaisseurAiguilles

' fond de l'aiguille sec (transparent ok)
Dim couleurSec As New SolidBrush(_couleurSec)
' stylo de contours aiguille sec (transparent ok)
Dim couleurSecContour As New Pen(_couleurSecContour, _EpaisseurAiguilles - 1)

points_aiguilles(0).X = arriere_x + X
points_aiguilles(0).Y = arriere_y + Y

points_aiguilles(1).X = epaisseur_haut_x + X
points_aiguilles(1).Y = epaisseur_haut_y + Y

points_aiguilles(2).X = long_x + X
points_aiguilles(2).Y = long_y + Y

points_aiguilles(3).X = epaisseur_bas_x + X
points_aiguilles(3).Y = epaisseur_bas_y + Y

If _FondAiguilles Then e.Graphics.FillPolygon(couleurSec, points_aiguilles)
If _ContourAiguille Then e.Graphics.DrawPolygon(couleurSecContour, points_aiguilles)
couleurSec.Dispose()
couleurSecContour.Dispose()
End If
'-----------------------
' Aiguille des Minutes
n = CSng(heure_actuel.Minute * 200 / 60)
z = CSng(n / 100 * PI)
u = CSng((n + 50) / 100 * PI)

long_x = CSng(Math.Sin(z) * 0.8 * X)
long_y = CSng(-Math.Cos(z) * 0.8 * Y)

arriere_x = CSng(-Math.Sin(z)) * 10
arriere_y = CSng(Math.Cos(z)) * 10

epaisseur_haut_x = CSng(Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_haut_y = CSng(-Math.Cos(u)) * _EpaisseurAiguilles

epaisseur_bas_x = CSng(-Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_bas_y = CSng(Math.Cos(u)) * _EpaisseurAiguilles

' fond de l'aiguille min (transparent ok)
Dim couleurMin As New SolidBrush(_couleurMin)
' stylo de contours aiguille sec (transparent ok)
Dim couleurMinContour As New Pen(_couleurMinContour, _EpaisseurAiguilles - 1)

points_aiguilles(0).X = arriere_x + X
points_aiguilles(0).Y = arriere_y + Y

points_aiguilles(1).X = epaisseur_haut_x + X
points_aiguilles(1).Y = epaisseur_haut_y + Y

points_aiguilles(2).X = long_x + X
points_aiguilles(2).Y = long_y + Y

points_aiguilles(3).X = epaisseur_bas_x + X
points_aiguilles(3).Y = epaisseur_bas_y + Y

If _FondAiguilles Then e.Graphics.FillPolygon(couleurMin, points_aiguilles)
If _ContourAiguille Then e.Graphics.DrawPolygon(couleurMinContour, points_aiguilles)

couleurMin.Dispose()
couleurMinContour.Dispose()
'-----------------------
' Aiguille des Heures
n = CSng(heure_actuel.Hour * 200 / 12 + heure_actuel.Minute * 200 / 60 / 12)
z = CSng(n / 100 * PI)
u = CSng((n + 50) / 100 * PI)

long_x = CSng(Math.Sin(z) * 0.6 * X)
long_y = CSng(-Math.Cos(z) * 0.6 * Y)

arriere_x = CSng(-Math.Sin(z)) * 10
arriere_y = CSng(Math.Cos(z)) * 10

epaisseur_haut_x = CSng(Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_haut_y = CSng(-Math.Cos(u)) * _EpaisseurAiguilles

epaisseur_bas_x = CSng(-Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_bas_y = CSng(Math.Cos(u)) * _EpaisseurAiguilles

' fond de l'aiguille heure (transparent ok)
Dim couleurHeure As New SolidBrush(_couleurHeure)
' stylo de contours aiguille sec (transparent ok)
Dim couleurHeureContour As New Pen(_couleurHeureContour, _EpaisseurAiguilles - 1)

points_aiguilles(0).X = arriere_x + X
points_aiguilles(0).Y = arriere_y + Y

points_aiguilles(1).X = epaisseur_haut_x + X
points_aiguilles(1).Y = epaisseur_haut_y + Y

points_aiguilles(2).X = long_x + X
points_aiguilles(2).Y = long_y + Y

points_aiguilles(3).X = epaisseur_bas_x + X
points_aiguilles(3).Y = epaisseur_bas_y + Y

If _FondAiguilles Then e.Graphics.FillPolygon(couleurHeure, points_aiguilles)
If _ContourAiguille Then e.Graphics.DrawPolygon(couleurHeureContour, points_aiguilles)

couleurHeure.Dispose()
couleurHeureContour.Dispose()

'-----------------------
' Chiffres
Dim taille_font As Single = Me.Font.Size
Dim font_txt As Font = Me.Font
Dim textCouleur As New SolidBrush(Me.ForeColor) '_couleurTexteCercle)

If _TexteHorloge Then

e.Graphics.DrawString("12", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font), taille_font / 2)
e.Graphics.DrawString("6", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font / 2), CSng(Me.Height - 2 * taille_font))
e.Graphics.DrawString("3", font_txt, textCouleur, CSng(Me.Width - taille_font - 2), CSng(Me.Height / 2 - taille_font))
e.Graphics.DrawString("9", font_txt, textCouleur, taille_font / 2, CSng(Me.Height / 2 - taille_font))

Else

e.Graphics.DrawString(".", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font / 2), -taille_font / 2)
e.Graphics.DrawString(".", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font / 2), CSng(Me.Height - 2 * taille_font))
e.Graphics.DrawString(".", font_txt, textCouleur, CSng(Me.Width - taille_font - 2), CSng(Me.Height / 2 - taille_font))
e.Graphics.DrawString(".", font_txt, textCouleur, taille_font / 2, CSng(Me.Height / 2 - taille_font))

End If
'-----------------------
textCouleur.Dispose()


'dessine le tout
MyBase.OnPaint(e)


End Sub 'OnPaint

2--------------------------------------------------
'--------------------------------------------------------
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
'
'Si _CercleHorloge dessine le cercle autour de l'horloge
If _CercleHorloge Then
couleurCercle = New Pen(_couleurCercle, 1)
rect = New Rectangle(2, 2, Me.Width - 3, Me.Height - 3)
e.Graphics.DrawEllipse(couleurCercle, rect)
End If

'heure actuelle
heure_actuel = DateTime.Now

'-----------------------
' Aiguille des Secondes (si propriété AiguilleSec à true)
If _AiguilleSec Then
n = CSng(heure_actuel.Second * 200 / 60)
z = CSng(n / 100 * PI)
u = CSng((n + 50) / 100 * PI)

long_x = CSng(Math.Sin(z) * 0.9 * X)
long_y = CSng(-Math.Cos(z) * 0.9 * Y)

arriere_x = CSng(-Math.Sin(z)) * 10
arriere_y = CSng(Math.Cos(z)) * 10

epaisseur_haut_x = CSng(Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_haut_y = CSng(-Math.Cos(u)) * _EpaisseurAiguilles

epaisseur_bas_x = CSng(-Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_bas_y = CSng(Math.Cos(u)) * _EpaisseurAiguilles



' fond de l'aiguille sec (transparent ok)
couleurSec = New SolidBrush(_couleurSec)
' stylo de contours aiguille sec (transparent ok)
couleurSecContour = New Pen(_couleurSecContour, _EpaisseurAiguilles - 1)


points_aiguilles(0).X = arriere_x + X
points_aiguilles(0).Y = arriere_y + Y

points_aiguilles(1).X = epaisseur_haut_x + X
points_aiguilles(1).Y = epaisseur_haut_y + Y

points_aiguilles(2).X = long_x + X
points_aiguilles(2).Y = long_y + Y

points_aiguilles(3).X = epaisseur_bas_x + X
points_aiguilles(3).Y = epaisseur_bas_y + Y

If _FondAiguilles Then e.Graphics.FillPolygon(couleurSec, points_aiguilles)
If _ContourAiguille Then e.Graphics.DrawPolygon(couleurSecContour, points_aiguilles)
' couleurSec.Dispose()
' couleurSecContour.Dispose()

End If


'-----------------------
' Aiguille des Minutes
n = CSng(heure_actuel.Minute * 200 / 60)
z = CSng(n / 100 * PI)
u = CSng((n + 50) / 100 * PI)

long_x = CSng(Math.Sin(z) * 0.8 * X)
long_y = CSng(-Math.Cos(z) * 0.8 * Y)

arriere_x = CSng(-Math.Sin(z)) * 10
arriere_y = CSng(Math.Cos(z)) * 10

epaisseur_haut_x = CSng(Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_haut_y = CSng(-Math.Cos(u)) * _EpaisseurAiguilles

epaisseur_bas_x = CSng(-Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_bas_y = CSng(Math.Cos(u)) * _EpaisseurAiguilles

' fond de l'aiguille min (transparent ok)
couleurMin = New SolidBrush(_couleurMin)
' stylo de contours aiguille sec (transparent ok)
couleurMinContour = New Pen(_couleurMinContour, _EpaisseurAiguilles - 1)

points_aiguilles(0).X = arriere_x + X
points_aiguilles(0).Y = arriere_y + Y

points_aiguilles(1).X = epaisseur_haut_x + X
points_aiguilles(1).Y = epaisseur_haut_y + Y

points_aiguilles(2).X = long_x + X
points_aiguilles(2).Y = long_y + Y

points_aiguilles(3).X = epaisseur_bas_x + X
points_aiguilles(3).Y = epaisseur_bas_y + Y

If _FondAiguilles Then e.Graphics.FillPolygon(couleurMin, points_aiguilles)
If _ContourAiguille Then e.Graphics.DrawPolygon(couleurMinContour, points_aiguilles)

' couleurMin.Dispose()
' couleurMinContour.Dispose()

'-----------------------
' Aiguille des Heures
n = CSng(heure_actuel.Hour * 200 / 12 + heure_actuel.Minute * 200 / 60 / 12)
z = CSng(n / 100 * PI)
u = CSng((n + 50) / 100 * PI)

long_x = CSng(Math.Sin(z) * 0.6 * X)
long_y = CSng(-Math.Cos(z) * 0.6 * Y)

arriere_x = CSng(-Math.Sin(z)) * 10
arriere_y = CSng(Math.Cos(z)) * 10

epaisseur_haut_x = CSng(Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_haut_y = CSng(-Math.Cos(u)) * _EpaisseurAiguilles

epaisseur_bas_x = CSng(-Math.Sin(u)) * _EpaisseurAiguilles
epaisseur_bas_y = CSng(Math.Cos(u)) * _EpaisseurAiguilles

' fond de l'aiguille heure (transparent ok)
couleurHeure = New SolidBrush(_couleurHeure)
' stylo de contours aiguille sec (transparent ok)
couleurHeureContour = New Pen(_couleurHeureContour, _EpaisseurAiguilles - 1)

points_aiguilles(0).X = arriere_x + X
points_aiguilles(0).Y = arriere_y + Y

points_aiguilles(1).X = epaisseur_haut_x + X
points_aiguilles(1).Y = epaisseur_haut_y + Y

points_aiguilles(2).X = long_x + X
points_aiguilles(2).Y = long_y + Y

points_aiguilles(3).X = epaisseur_bas_x + X
points_aiguilles(3).Y = epaisseur_bas_y + Y

If _FondAiguilles Then e.Graphics.FillPolygon(couleurHeure, points_aiguilles)
If _ContourAiguille Then e.Graphics.DrawPolygon(couleurHeureContour, points_aiguilles)

'couleurHeure.Dispose()
'couleurHeureContour.Dispose()

'-----------------------
' Chiffres
taille_font = Me.Font.Size
font_txt = Me.Font
textCouleur = New SolidBrush(Me.ForeColor)

If _TexteHorloge Then

e.Graphics.DrawString("12", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font), taille_font / 2)
e.Graphics.DrawString("6", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font / 2), CSng(Me.Height - 2 * taille_font))
e.Graphics.DrawString("3", font_txt, textCouleur, CSng(Me.Width - taille_font - 2), CSng(Me.Height / 2 - taille_font))
e.Graphics.DrawString("9", font_txt, textCouleur, taille_font / 2, CSng(Me.Height / 2 - taille_font))

Else

e.Graphics.DrawString(".", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font / 2), -taille_font / 2)
e.Graphics.DrawString(".", font_txt, textCouleur, CSng(Me.Width / 2 - taille_font / 2), CSng(Me.Height - 2 * taille_font))
e.Graphics.DrawString(".", font_txt, textCouleur, CSng(Me.Width - taille_font - 2), CSng(Me.Height / 2 - taille_font))
e.Graphics.DrawString(".", font_txt, textCouleur, taille_font / 2, CSng(Me.Height / 2 - taille_font))

End If
'-----------------------
'textCouleur.Dispose()


'dessine le tout
MyBase.OnPaint(e)


End Sub 'OnPaint

-----------------------------------------------
'Modif sur le travail de la source de CGi et Neo.51
'Merci à eux pour leurs tutos : http://chgi.developpez.com/dotnet/compo1/vb/
kbalist Messages postés 36 Date d'inscription jeudi 28 janvier 2010 Statut Membre Dernière intervention 6 février 2011
21 avril 2010 à 10:19
je suis intéressé par tes 2 sources pour comparer...
si je suis le seul intéressé, tu peux me les envoyer en MP ?

quand tu dis que tu disposes les variables à la fin, tu n'utilises pas d'instruction spécifique, elles sont juste libérées par le retour à la routine appelante (car ce sont des variables locales) ?

tu dis que ta mémoire disponible au début baisse de 40 KO/s, c'est une fuite de mémoire, non ? et pourquoi s'arrête-t-elle ?

tu parlais du DoEvents() pour l'animation :
- je ne connais pas d'autre méthodes (simples !) pour forcer le redessin de l'écran
- elle est conseillée dans plusieurs sites et exemples (je sais, ce n'est pas une preuve absolue !)
- c'est quand même facile à mettre en oeuvre au vu de la longueur de la fonction Animation()
Adn56 Messages postés 1172 Date d'inscription jeudi 24 mai 2007 Statut Membre Dernière intervention 28 septembre 2013 1
20 avril 2010 à 20:20
Tes questions sont bonnes et tres justifiées !
J'ai essayé sur une source de base d'une horloge le changement conseillé par bigboss (car je pense comme toi au niveau des variables)
le résultat ?
ben mitigé, la source de base bouff 11Mo pour juste afficher une horloge analogique et augmente de 40Ko/sec.
Aprés avoir déclarer toutes mes variables dans le module de la form (comme le conseil bigboss) je ne bouff que 10MO et une augmentation que de 20Ko/sec !
donc à priori cela fontionne bien comme bigboss l'indique.
Seulement aprés 30minutes de marche de mes deux sources lancées simultannément, l'une atteind 15MO et continue d'augmenter et l'autre se stabilise à 13Mo !
Je vous laisse deviner celle qui se stabilise ^^
Celle qui utilise les variables dans les fonctions et qui les disposes à la fin. c'est pas trés clair pour moi.
Je ne suis pas assez 'pro' pour tout piger, mais si besoin je post les deux sources pour que vous puissiez y jeter un coup d'oeil. Je trouve tout de même assez lourd 14Mo de ressource, juste pour afficher une horloge ! non ?
++
kbalist Messages postés 36 Date d'inscription jeudi 28 janvier 2010 Statut Membre Dernière intervention 6 février 2011
20 avril 2010 à 19:15
merci de vos remarques qui me font progresser les gars...

pour BIGBOSS9 :
- j'ai rectifié le source pour tenir compte de ta remarque sur les fuites de mémoire avec des New dans les paramètres des fonctions. ça m'évoque 2 questions :

*comment vérifier qu'il n'y a pas de fuite de mémoire ? (le gestionnaire de programmes montre une mémoire très variable avec ou sans programme qui tourne)

*y a-t-il d'autres erreurs du même genre à ne pas faire ?

- j'ai plus de mal avec ta remarque :
"Pour des raisons d'optimisation, déclare le plus tes variables en dehors des procédures. Sinon, chaque fois que ta form est redessinée, tu réutilise de la mémoire pour rien."
faut-il comprendre que si j'utilise dans la routine DrawRotatedString un centre de rotation, il vaut mieux le déclarer et le définir dans la routine qui appelle DrawRotatedString (Form1_Paint dans mon exemple) et le passer en paramètre à DrawRotatedString , plutôt que de le définir dans DrawRotatedString elle-même ? ou le déclarer en global si c'est toujours le même ?

- pour résumer si j'ai bien compris : il vaudrait mieux déclarer le point-origine courant comme une variable globale avec

Dim Origine As PointF = New PointF(x1, y1)

et, après calculs, modifier Origine.x et Origine.y à chaque pas dans la routine Animation pour utiliser cette variable globale dans Form1_Paint ?

cela me gênait à priori car on m'a dit qu'il valait mieux utiliser des variables locales que globales.
de plus je voulais faire un exemple facile à réutiliser (copier-coller) par d'autres.

pour ADN56 : bonne remarque pour le double-buffer, j'oublie toujours !
c'est vrai que je ne pensais pas vraiment à l'aspect animation, j'ai fait celle-ci juste pour montrer comment utiliser les routines d'affichage du texte et de l'ellipse.

désolé si je suis trop long et si je pose trop de questions, mais je pense que cela peut permettre à d'autres autodidactes comme moi de faire des progrès sans perdre de temps à "réinventer la roue" ;-)

encore merci pour vos réponses et vos remarques constructives
Adn56 Messages postés 1172 Date d'inscription jeudi 24 mai 2007 Statut Membre Dernière intervention 28 septembre 2013 1
12 avril 2010 à 20:06
comme le dit bigboss, y'a du flick ^^
essaye déja (gourmand mais bon) de placer ta form en doublebuffer=true,
cela évitera le clignotement de ta rotation ! dés plus désagréable à voir.
sinon bien vu les fonctions. Sauf pour animation() il doit y avoir mieux qu'un doevent non ?
bon j'suis pas pro, mais au pif...un timer ? un tread ?
@ suivre donc...et merci pour l'exemple.
cs_bigboss9 Messages postés 162 Date d'inscription jeudi 22 janvier 2004 Statut Membre Dernière intervention 20 juillet 2013
10 avril 2010 à 10:11
Pour info :

A partir du Framework 3.0 je crois, on peut utiliser :

Using TempBrush as New LoineaGradientBrush(Me.ClientRectangle, Color.Red,Color.Blue,Gradient.Vertical)

'instructions
e.graphic.FillRectangle(Me.ClientRectangle, TempBrush

End Using

Au moment du End Using, il libère la ressource automatiquement.
Mais dans tous les cas et pour avoir testé, cela ne vaut pas la déclaration de tes variables en dehors des procédures/fonctions. En effet, le temps de libérer la mémoire, cela ralenti le processus de dessin.

A noter que cette méthode n'est valable que pour les objets disposants de l'interface IDisposable, c'est à dire comprenant la méthode Dispose().
cs_bigboss9 Messages postés 162 Date d'inscription jeudi 22 janvier 2004 Statut Membre Dernière intervention 20 juillet 2013
10 avril 2010 à 10:07
C'est bien et ca fait plaisir. Par contre :

- N'utilise pas New Pen(Color.Blue, 3) dans une instruction car tu ne peux plus libérer ton objet ensuite. A chaque fois que ta form est redessinée, il en créee un nouveau ! 1ère fuite de mémoire.

- Idem pour New Rectangle(), New Point(), etc...
- Pour des raisons d'optimisation, déclare le plus tes variables en dehors des procédures. Sinon, chaque fois que ta form est redessinée, tu réutilise de la mémoire pour rien.
- Ne fais pas de procédures qui dessinent. Utilise plutot une fonction qui te retourne ton GraphicPath. Cela te permet de séparer les actions, mieux évaluer le code et faciliter sa mise à jour et son élimination des bugs.

Concernant laquelle de ces deux méthodes choisir, on dira que cela dépends de leur rapidité. Il faudrait mesurer. De plus, les calculs ne sont pas le fort du .Net. L'utilisation d'une DLL écrite en C++ serait fort appréciable pour avoir de meilleures performances.

Et dire que je suis tyranique ... %)
Rejoignez-nous