En réponse à la source (
http://www.vbfrance.com/codes/BARGRAPHE-VUMETRE_51503.aspx), voici un control VuMètre 100% personnalisable. Développé un peu à la vas-vite, il mérite néanmoins d'être posté ici, ce genre de controls (exploitables en l'état) n'étant pas légion ici.
Fonctionnalités :
- Gestion des repères de division (appelés 'Région')
- Gestion de la couleur des Régions
- Gestion de la taille des barres et de leur interval
- Développé à partir d'un control Trackbar, le controle peut être utilisé comme tel (après correction d'un bug de précision)
- Quelques effets pour lui donner plus d'allure
- Gestion de l'effet d'affichage du "Maximum" avec possibilité de reglage sur le temps d'affichage et de déclin
- Compatible uniquement sur le mode Vertical
- Personnalisation de l'affichage du texte
- Personnalisation de l'affichage de l'effet d'ombre 3D
--------------------------------------------------------------------------------------------
Quelques bogues néanmoins :
- Impossibilité de s'en servir en Trackbar à cause d'une erreur de précision sur une division qui fausse le calcul de la position de la barre de sélection.
Source / Exemple :
Imports System.ComponentModel
Imports System.Threading
'#####################################################################################################################################
'#####################################################################################################################################
'
' SOURCE DEPOSEE SUR VBFRANCE
' COPYRIGHT ALEXANDRE SCELLIER 2010
' NE DOIT PAS ETRE UTILISE DANS UN BUT COMMERCIAL, SEULEMENT PEDAGOGIQUE
'
'#####################################################################################################################################
'#####################################################################################################################################
Public Class VuMetre
#Region "HERITAGE"
'#####################################################################
'##### HERITAGE DU CONTROL DEPUIS UN WINDOWS.FORM.TRACKBAR
'#####################################################################
Inherits TrackBar
#End Region
#Region "VARIABLES"
#Region "Variables qui sont reliées à des propriétés"
'#####################################################################
'##### VARIABLES EN RELATION AVEC UNE PROPRIETE
'#####################################################################
Public Enum OmberEffectMode
Horizontal
Vertical
End Enum
Private m_Prop_BarInterval As Integer = 1
Private m_Prop_Padding_RightAndLeft As Integer = 4
Private m_Prop_BarHeight As Integer = 3
Private m_Prop_SplitZone_1 As Integer = 10
Private m_Prop_SplitZone_2 As Integer = 50
Private m_Prop_SplitZone_Color_1 As Color = Color.FromArgb(15, 137, 112)
Private m_Prop_SplitZone_Color_2 As Color = Color.FromArgb(137, 116, 15)
Private m_Prop_SplitZone_Color_3 As Color = Color.FromArgb(137, 15, 40)
Private m_Prop_SplitZone_Color_Default As Color = Color.Gray
Private m_Prop_ShowValue As Boolean = True
Private m_Prop_ShowCursor As Boolean = True
Private m_Prop_ShowRegions As Boolean = True
Private m_Prop_ShowColorEffect As Boolean = True
Private m_Prop_Font As Font = New Font("Tahoma", 7, FontStyle.Bold)
Private m_Prop_Symbol As String = "%"
Private m_Prop_FontColor As Color = Color.White
Private m_Prop_MaximumBarColor As Color = Color.White
Private m_Prop_MaximumBarHeight As Integer = 2
Private m_Prop_ShowMaximumBar As Boolean = True
Private m_Prop_ShowAnimationMaximumBar As Boolean = True
Private m_Prop_MaximumTime As Integer = 10
Private m_Prop_MaximumTimeDelay As Integer = 5
Private m_Prop_OmberEffectColor_1 As Color = Color.Transparent
Private m_Prop_OmberEffectColor_2 As Color = Color.FromArgb(100, 0, 0, 0)
Private m_Prop_OmberEffectType As OmberEffectMode = OmberEffectMode.Vertical
#End Region
'#####################################################################
'##### VARIABLES SANS RELATION AVEC UNE PROPRIETE
'#####################################################################
Private mBarSize As Size
Private mPadding_TopAndBottom As Integer = 10
Private mBarBrush As SolidBrush
Private mBarRectangle As Rectangle
Private mBorderPen As Pen
Private mBarMouseDown As Boolean = False
Private Temp_ValuePercent As Integer
Private Temp_Percent As Integer
Private Temp_Color As Color
Private Temp_ValueY As Integer
Private Temp_CursorColor As Color
Private Temp_Cycles As Integer
Private mScrollRectangle As Rectangle
Private mTextSize As SizeF
Private Temp_Maximum As Integer
Private Temp_MaximumValue As Integer
Private Temp_MaximumAlpha As Integer = 255
Private mEffectBrush As Drawing2D.LinearGradientBrush
Private mMaximumTime As Integer = 10
Private mMaximumTimeDelay As Integer = 5
#End Region
#Region "PROPRIETES"
'#####################################################################
'#####
'#####################################################################
<Description(""), Category("OmberEffect")> _
Public Property OmberEffectColor_1() As Color
Get
Return m_Prop_OmberEffectColor_1
End Get
Set(ByVal value As Color)
m_Prop_OmberEffectColor_1 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("OmberEffect")> _
Public Property OmberEffectColor_2() As Color
Get
Return m_Prop_OmberEffectColor_2
End Get
Set(ByVal value As Color)
m_Prop_OmberEffectColor_2 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("OmberEffect")> _
Public Property OmberEffect() As OmberEffectMode
Get
Return m_Prop_OmberEffectType
End Get
Set(ByVal value As OmberEffectMode)
m_Prop_OmberEffectType = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Affichage")> _
Public Property ShowText() As Boolean
Get
Return m_Prop_ShowValue
End Get
Set(ByVal value As Boolean)
m_Prop_ShowValue = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Affichage")> _
Public Property ShowSelectionCursor() As Boolean
Get
Return m_Prop_ShowCursor
End Get
Set(ByVal value As Boolean)
m_Prop_ShowCursor = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Affichage")> _
Public Property ShowColorRegions() As Boolean
Get
Return m_Prop_ShowRegions
End Get
Set(ByVal value As Boolean)
m_Prop_ShowRegions = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Affichage")> _
Public Property ShowOmberEffect() As Boolean
Get
Return m_Prop_ShowColorEffect
End Get
Set(ByVal value As Boolean)
m_Prop_ShowColorEffect = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Affichage")> _
Public Property ShowMaximumBar() As Boolean
Get
Return m_Prop_ShowMaximumBar
End Get
Set(ByVal value As Boolean)
m_Prop_ShowMaximumBar = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Maximum")> _
Public Property CyclesDelay() As Integer
Get
Return m_Prop_MaximumTimeDelay
End Get
Set(ByVal value As Integer)
m_Prop_MaximumTimeDelay = value
mMaximumTimeDelay = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Maximum")> _
Public Property CyclesBeforeReset() As Integer
Get
Return m_Prop_MaximumTime
End Get
Set(ByVal value As Integer)
m_Prop_MaximumTime = value
mMaximumTime = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Maximum")> _
Public Property ShowMaximumBarAnimation() As Boolean
Get
Return m_Prop_ShowAnimationMaximumBar
End Get
Set(ByVal value As Boolean)
m_Prop_ShowAnimationMaximumBar = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Maximum")> _
Public Property MaximumBarHeight() As Integer
Get
Return m_Prop_MaximumBarHeight
End Get
Set(ByVal value As Integer)
m_Prop_MaximumBarHeight = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Maximum")> _
Public Property MaximumBarColor() As Color
Get
Return m_Prop_MaximumBarColor
End Get
Set(ByVal value As Color)
m_Prop_MaximumBarColor = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Couleurs")> _
Public Property DefaultBarColor() As Color
Get
Return m_Prop_SplitZone_Color_Default
End Get
Set(ByVal value As Color)
m_Prop_SplitZone_Color_Default = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Style")> _
Public Property BarHeight() As Integer
Get
Return m_Prop_BarHeight
End Get
Set(ByVal value As Integer)
m_Prop_BarHeight = value
mBarSize = New Size(Me.Width, m_Prop_BarHeight)
mScrollRectangle = New Rectangle(m_Prop_Padding_RightAndLeft, mPadding_TopAndBottom, Me.Width - m_Prop_Padding_RightAndLeft * 2, Me.Height - mPadding_TopAndBottom * 2)
Me.Refresh()
End Set
End Property
<Description(""), Category("Style")> _
Public Property BarInterval() As Integer
Get
Return m_Prop_BarInterval
End Get
Set(ByVal value As Integer)
m_Prop_BarInterval = value : Me.Refresh()
mBarSize = New Size(Me.Width, m_Prop_BarHeight)
mScrollRectangle = New Rectangle(m_Prop_Padding_RightAndLeft, mPadding_TopAndBottom, Me.Width - m_Prop_Padding_RightAndLeft * 2, Me.Height - mPadding_TopAndBottom * 2)
Me.Refresh()
End Set
End Property
<Description(""), Category("Marges")> _
Public Property LeftAndRightMargin() As Integer
Get
Return m_Prop_Padding_RightAndLeft
End Get
Set(ByVal value As Integer)
m_Prop_Padding_RightAndLeft = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Régions")> _
Public ReadOnly Property RegionPercent_3() As Integer
Get
Return 100 - m_Prop_SplitZone_2 - m_Prop_SplitZone_1
End Get
End Property
<Description(""), Category("Régions")> _
Public Property RegionPercent_2() As Integer
Get
Return m_Prop_SplitZone_2
End Get
Set(ByVal value As Integer)
m_Prop_SplitZone_2 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Régions")> _
Public Property RegionPercent_1() As Integer
Get
Return m_Prop_SplitZone_1
End Get
Set(ByVal value As Integer)
m_Prop_SplitZone_1 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Couleurs")> _
Public Property RegionColor_1() As Color
Get
Return m_Prop_SplitZone_Color_3
End Get
Set(ByVal value As Color)
m_Prop_SplitZone_Color_3 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Couleurs")> _
Public Property RegionColor_2() As Color
Get
Return m_Prop_SplitZone_Color_2
End Get
Set(ByVal value As Color)
m_Prop_SplitZone_Color_2 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Couleurs")> _
Public Property RegionColor_3() As Color
Get
Return m_Prop_SplitZone_Color_1
End Get
Set(ByVal value As Color)
m_Prop_SplitZone_Color_1 = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Légende")> _
Public Property TextSymbol() As String
Get
Return m_Prop_Symbol
End Get
Set(ByVal value As String)
m_Prop_Symbol = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Légende")> _
Public Property TextFont() As Font
Get
Return m_Prop_Font
End Get
Set(ByVal value As Font)
m_Prop_Font = value : Me.Refresh()
End Set
End Property
<Description(""), Category("Légende")> _
Public Property TextColor() As Color
Get
Return m_Prop_FontColor
End Get
Set(ByVal value As Color)
m_Prop_FontColor = value : Me.Refresh()
End Set
End Property
#End Region
#Region "DESSINER LE CONTROLE"
Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
'#####################################################################
'##### DESSINER LE FOND DU CONTROL (RAPPEL : ON TRAVAILLE EN %)
'#####################################################################
'##### EFFACER LE FOND DU CONTROL
pevent.Graphics.Clear(Color.Black)
pevent.Graphics.FillRectangle(Brushes.Black, mScrollRectangle)
'##### METTRE A ZERO LES PARAMETRES QUI VARIENT
Temp_CursorColor = Nothing
Temp_ValueY = 0
'##### ON RAMENE EN POURCENTAGE LA VALEUR DU VU-METRE (EN FONCTION DE LA VALEUR)
Temp_ValuePercent = CInt(Math.Round((Me.Value * 100) / Me.Maximum, 0))
'##### ON DESSINE CHAQUE ELEMENT
For i As Integer = mScrollRectangle.Top To (mScrollRectangle.Height + mPadding_TopAndBottom) Step (m_Prop_BarInterval + mBarSize.Height)
'##### CALCUL EN POURCENTAGE DE LA VALEUR ACTUELLE (EN FONCTION DE Y)
Temp_Percent = CInt((i * 100) / (mScrollRectangle.Height + mPadding_TopAndBottom))
Temp_Color = Nothing
'##### GESTION DES DIFFERENTES REGIONS DE COULEUR
If m_Prop_ShowRegions Then
If Temp_Percent > 0 And Temp_Percent <= m_Prop_SplitZone_1 Then
Temp_Color = Color.FromArgb(80, m_Prop_SplitZone_Color_3.R, m_Prop_SplitZone_Color_3.G, m_Prop_SplitZone_Color_3.B)
ElseIf Temp_Percent > m_Prop_SplitZone_1 And Temp_Percent <= m_Prop_SplitZone_2 Then
Temp_Color = Color.FromArgb(80, m_Prop_SplitZone_Color_2.R, m_Prop_SplitZone_Color_2.G, m_Prop_SplitZone_Color_2.B)
ElseIf Temp_Percent >= m_Prop_SplitZone_2 Then
Temp_Color = Color.FromArgb(80, m_Prop_SplitZone_Color_1.R, m_Prop_SplitZone_Color_1.G, m_Prop_SplitZone_Color_1.B)
End If
Else
Temp_Color = Color.FromArgb(80, m_Prop_SplitZone_Color_Default.R, m_Prop_SplitZone_Color_Default.G, m_Prop_SplitZone_Color_Default.B)
End If
'##### GESTION DE L'AFFICHAGE DES VALEURS
If (100 - Temp_ValuePercent) < Temp_Percent Then
If Temp_ValueY = 0 Then
Temp_ValueY = i
End If
If m_Prop_ShowCursor Then
If Temp_CursorColor = Nothing Then
Temp_CursorColor = Color.FromArgb(255, Temp_Color.R, Temp_Color.G, Temp_Color.B)
End If
End If
'##### ON DESSINE LA BARRE AVEC LE STATUT "ACTIF"
mBarBrush = New SolidBrush(Color.FromArgb(255, Temp_Color.R, Temp_Color.G, Temp_Color.B))
Else
'##### ON DESSINE LA BARRE AVEC LE STATUT "INACTIF"
mBarBrush = New SolidBrush(Temp_Color)
End If
mBarRectangle = New Rectangle(0, i, mBarSize.Width, mBarSize.Height)
pevent.Graphics.FillRectangle(mBarBrush, mBarRectangle)
mBarBrush.Dispose()
Next
'##### GESTION DU MAXIMUM
If m_Prop_ShowMaximumBar Then
If m_Prop_ShowAnimationMaximumBar Then
'##### GESTION DES VALEURS -MAXIMUM & -MINIMUM
If Temp_Maximum <= mScrollRectangle.Top Then
mBarRectangle = New Rectangle(0, mScrollRectangle.Top, mBarSize.Width, m_Prop_MaximumBarHeight)
pevent.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(Temp_MaximumAlpha, m_Prop_MaximumBarColor.R, m_Prop_MaximumBarColor.G, m_Prop_MaximumBarColor.B)), mBarRectangle)
ElseIf Temp_Maximum <= 0 Then
mBarRectangle = New Rectangle(0, mScrollRectangle.Top + mScrollRectangle.Height - 2, mBarSize.Width, m_Prop_MaximumBarHeight)
pevent.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(Temp_MaximumAlpha, m_Prop_MaximumBarColor.R, m_Prop_MaximumBarColor.G, m_Prop_MaximumBarColor.B)), mBarRectangle)
Else
mBarRectangle = New Rectangle(0, Temp_Maximum, mBarSize.Width, m_Prop_MaximumBarHeight)
pevent.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(Temp_MaximumAlpha, m_Prop_MaximumBarColor.R, m_Prop_MaximumBarColor.G, m_Prop_MaximumBarColor.B)), mBarRectangle)
End If
Else
mBarRectangle = New Rectangle(0, Temp_Maximum, mBarSize.Width, m_Prop_MaximumBarHeight)
pevent.Graphics.FillRectangle(New SolidBrush(m_Prop_MaximumBarColor), mBarRectangle)
End If
End If
'##### CODE INHERENT AU TEST EN MODE DESIGN (EDITEUR VS)
If DesignMode Then
pevent.Graphics.DrawRectangle(Pens.Blue, mScrollRectangle)
End If
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
'#####################################################################
'##### DESSINER LE CONTROLE (PHASE 2)
'#####################################################################
'##### GESTION DE L'EFFET D'OMBRE
If m_Prop_ShowColorEffect Then
Select Case m_Prop_OmberEffectType
Case OmberEffectMode.Horizontal
mEffectBrush = New Drawing2D.LinearGradientBrush(Me.ClientRectangle, m_Prop_OmberEffectColor_1, m_Prop_OmberEffectColor_2, Drawing2D.LinearGradientMode.Horizontal)
e.Graphics.FillRectangle(mEffectBrush, Me.ClientRectangle)
Case OmberEffectMode.Vertical
mEffectBrush = New Drawing2D.LinearGradientBrush(Me.ClientRectangle, m_Prop_OmberEffectColor_1, m_Prop_OmberEffectColor_2, Drawing2D.LinearGradientMode.Vertical)
e.Graphics.FillRectangle(mEffectBrush, Me.ClientRectangle)
End Select
mEffectBrush.Dispose()
End If
'##### GESTION DE L'AFFICHAGE TEXTUEL
If m_Prop_ShowValue Then
e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
mTextSize = e.Graphics.MeasureString(Me.Value & m_Prop_Symbol, m_Prop_Font)
e.Graphics.DrawString(Me.Value & m_Prop_Symbol, m_Prop_Font, Brushes.Black, CInt((Me.Width / 2) - (mTextSize.Width / 2)), CInt((Me.Height / 2) - (mTextSize.Height / 2)) - 1)
e.Graphics.DrawString(Me.Value & m_Prop_Symbol, m_Prop_Font, Brushes.Black, CInt((Me.Width / 2) - (mTextSize.Width / 2)), CInt((Me.Height / 2) - (mTextSize.Height / 2)) + 1)
e.Graphics.DrawString(Me.Value & m_Prop_Symbol, m_Prop_Font, Brushes.White, CInt((Me.Width / 2) - (mTextSize.Width / 2)), CInt((Me.Height / 2) - (mTextSize.Height / 2)))
End If
'##### DESSINER LES MARGES
e.Graphics.FillRectangle(Brushes.Black, 0, 0, m_Prop_Padding_RightAndLeft, Me.Height)
e.Graphics.FillRectangle(Brushes.Black, Me.Width - m_Prop_Padding_RightAndLeft, 0, m_Prop_Padding_RightAndLeft, Me.Height)
e.Graphics.FillRectangle(Brushes.Black, 0, 0, Me.Width, mScrollRectangle.Top)
e.Graphics.FillRectangle(Brushes.Black, 0, mScrollRectangle.Top +mScrollRectangle.Height, Me.Width, mScrollRectangle.Top)
'##### GESTION DU CURSEUR DE SELECTION
If m_Prop_ShowCursor Then
mBarBrush = New SolidBrush(Temp_CursorColor)
mBarRectangle = New Rectangle(0, Temp_ValueY, mBarSize.Width, mBarSize.Height)
e.Graphics.FillRectangle(mBarBrush, mBarRectangle)
End If
End Sub
#End Region
#Region "METTRE A JOUR LE CONTROLE VISUELLEMENT"
'#####################################################################
'##### MISE A JOUR GRAPHIQUE DU COMPOSANT
'#####################################################################
Private Sub VuMetre_MouseCaptureChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseCaptureChanged
MyBase.Refresh() '// Concerne MouseEnter & MouseLeave
End Sub
Private Sub VuMetre_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
MyBase.Refresh()
End Sub
Private Sub VuMetre_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
MyBase.Refresh()
End Sub
Private Sub VuMetre_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
MyBase.Refresh()
End Sub
Private Sub VuMetre_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel
MyBase.Refresh()
End Sub
Protected Overrides Sub OnValueChanged(ByVal e As System.EventArgs)
'##### Gestion du Maximum (Sans Timer)
If Me.Value > Temp_MaximumValue Then
Temp_MaximumValue = Me.Value
Temp_Maximum = (Me.Height - CInt((Me.Value * (mScrollRectangle.Height + mPadding_TopAndBottom)) / Me.Maximum) - mPadding_TopAndBottom)
If m_Prop_ShowMaximumBar Then
If m_Prop_ShowAnimationMaximumBar Then
Temp_MaximumAlpha = 255
End If
mMaximumTime = 10
mMaximumTimeDelay = 5
End If
End If
MyBase.OnValueChanged(e)
MyBase.Refresh()
'#####################################################################
'##### CALCUL APRES AFFICHAGE DES VALEURS DU MAXIMUM
'#####################################################################
'##### On desactive le calcul en mode Design (Editeur VS)
If Not DesignMode Then
If m_Prop_ShowMaximumBar Then
'##### Gestion du Maximum (Sans Timer)
If mMaximumTime = 0 Then
mMaximumTime = 10
mMaximumTimeDelay = 5
Temp_Maximum = mScrollRectangle.Height
Temp_MaximumValue = 0
If m_Prop_ShowAnimationMaximumBar Then
Temp_MaximumAlpha = 255
End If
Else
'##### Gestion du Maximum (Sans Timer)
If m_Prop_ShowAnimationMaximumBar Then
mMaximumTime -= 1
mMaximumTimeDelay -= 1
'##### Selon le délai d'affichage défini, on diminue le maximum
If mMaximumTimeDelay <= 0 Then
If Temp_MaximumAlpha - 50 >= 0 Then
Temp_MaximumAlpha -= 50
Else
Temp_MaximumAlpha = 0
End If
Temp_Maximum += (mBarSize.Height + m_Prop_BarInterval)
End If
End If
End If
End If
End If
End Sub
#End Region
#Region "CALCUL DES VARIABLES INDEPENDANTES"
Private Sub VuMetre_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
'#####################################################################
'##### AJUSTEMENT DES VARIABLES POUR LA MAJ DU CONTROL AU REDIMENSIONNEMENT
'#####################################################################
Temp_ValuePercent = CInt(Math.Round((Me.Value * 100) / Me.Maximum, 0))
mBarSize = New Size(Me.Width, m_Prop_BarHeight)
mScrollRectangle = New Rectangle(m_Prop_Padding_RightAndLeft, mPadding_TopAndBottom, Me.Width - m_Prop_Padding_RightAndLeft * 2, Me.Height - mPadding_TopAndBottom * 2)
MyBase.Refresh()
End Sub
#End Region
End Class
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.