Vengono determinate le facce, rispettivamente, laterali e superiori di ciascuna barra:
Dim FacciaVerticale() As Point = {New Point(posX + l, posY + h), New Point(posX + l + p, posY + h + p), _
New Point(posX + l + p, posY + p), New Point(posX + l, posY)}
Dim FacciaSuperiore() As Point = {New Point(posX + l, posY + h), New Point(posX + l + p, posY + h + p), _
New Point(posX + p, posY + h + p), New Point(posX, posY + h)}
A questo punto, è possibile disegnare le barre stesse:
gr.FillRectangle(coloreF, posX, posY, l, h)
gr.FillPolygon(coloreL, FacciaVerticale)
gr.FillPolygon(coloreS, FacciaSuperiore)
End Sub
Private Sub PictureBox1_Paint1(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles PictureBox1.Paint
gr = e.Graphics
Vengono definiti i colori di ciascuna faccia dei parallelepipedi, in modo che quelle relative al primo anno di riferimento (dunque, alla prima fila) siano gialle, per il secondo anno arancio e, di seguito, blu. Nell'esempio riportato, comunque, saranno visualizzate solamente due file, che appariranno pertanto, rispettivamente, gialle ed arancio.
Dim bluF As Color = Color.FromArgb(178, 0, 0, 255)
Dim bluS As Color = Color.FromArgb(204, 50, 150, 200)
Dim bluL As Color = Color.FromArgb(204, 50, 100, 150)
Dim brushBluF As New SolidBrush(bluF)
Dim brushBluS As New SolidBrush(bluS)
Dim brushBluL As New SolidBrush(bluL)
Dim rossoF As Color = Color.FromArgb(217, 247, 100, 30)
Dim rossoS As Color = Color.FromArgb(204, 209, 111, 81)
Dim rossoL As Color = Color.FromArgb(204, 170, 97, 74)
Dim brushRossoF As New SolidBrush(rossoF)
Dim brushRossoS As New SolidBrush(rossoS)
Dim brushRossoL As New SolidBrush(rossoL)
Dim gialloF As Color = Color.FromArgb(217, 255, 255, 50)
Dim gialloS As Color = Color.FromArgb(204, 230, 230, 50)
Dim gialloL As Color = Color.FromArgb(204, 177, 177, 75)
Dim brushGialloF As New SolidBrush(gialloF)
Dim brushGialloS As New SolidBrush(gialloS)
Dim brushGialloL As New SolidBrush(gialloL)
Si impone inoltre che, laddove il valore massimo ottenuto sia maggiore di zero, questo venga approssimato per eccesso al multiplo di dieci più vicino, mentre, in caso contrario, si esca immediatamente.
If (maxValore Mod 10) > 0 Then
maxValore = (maxValore \ 10) * 10 + 10
ElseIf maxValore = 0 Then
Exit Sub
End If
Oltre a definire numerosi aspetti puramente tecnici, si impone che, relativamente alla seconda fila di parallelepipedi, l'origine sia traslata nel punto (10, 10):
Dim penAssi As New Pen(Color.DarkGray, -1)
Dim labelFont As New Font("Arial", 3, FontStyle.Regular)
Dim ColoreTesto As New SolidBrush(Color.Blue)
x1 = 0
y1 = 0
x2 = CType(bordo + numeroValori / nFile * 10 + profRiferimento + bordoDX, Single)
y2 = bordo + maxValore + profRiferimento + bordo
scaleX = Me.PictureBox1.Width / (x2 - x1)
scaleY = Me.PictureBox1.Height / (y2 - y1)
Dim larghezza As Integer = CType(x2 * (Me.Size.Height - 40) / y2, Integer)
If larghezza <= Me.Size.Width Then
PictureBox1.Width = larghezza
PictureBox1.Height = Me.Size.Height - 40
Else
PictureBox1.Width = Me.Size.Width
PictureBox1.Height = CType(y2 * Me.Size.Width / x2, Integer)
End If
gr.ScaleTransform(scaleX, -scaleY)
gr.TranslateTransform(x1, -y2)
dopo aver pulito la casella, viene disegnata la griglia:
gr.Clear(Color.White)
Dim colorePareti As Color = Color.FromArgb(218, 221, 223)
Dim brushPareti As New SolidBrush(colorePareti)
Dim SistemaDiRiferimento() As Point = { _
New Point(CInt(x1 + bordo), CInt(y1 + bordo)), _
New Point(CInt(x2 - profRiferimento - bordoDX), CInt(y1 + bordo)), _
New Point(CInt(x2 - bordoDX), CInt(y1 + bordo + profRiferimento)), _
New Point(CInt(x2 - bordoDX), CInt(y2 - bordo)), _
New Point(CInt(x1 + bordo + profRiferimento), CInt(y2 - bordo)), _
New Point(CInt(x1 + bordo), CInt(y2 - bordo - profRiferimento))}
gr.FillPolygon(brushPareti, SistemaDiRiferimento)
gr.DrawPolygon(Pens.DarkGray, SistemaDiRiferimento)
For xScan As Single = 0 To CSng((numeroValori / nFile * 10) - 10) Step 10
gr.DrawLine(penAssi, xScan + bordo + profRiferimento, y1 + bordo + profRiferimento, _
xScan + bordo + profRiferimento, maxValore + bordo + profRiferimento)
gr.DrawLine(penAssi, xScan + bordo + profRiferimento, y1 + bordo + profRiferimento, _
xScan + bordo, y1 + bordo)
Next xScan
For yScan As Single = 0 To maxValore - 10 Step 10
Dim lunghezza As Integer = CInt(numeroValori / nFile * 10)
gr.DrawLine(penAssi, x1 + bordo + profRiferimento, yScan + bordo + profRiferimento, _
lunghezza + bordo + profRiferimento, yScan + bordo + profRiferimento)
gr.DrawLine(penAssi, x1 + bordo, yScan + bordo, x1 + bordo + profRiferimento, _
yScan + bordo + profRiferimento)
Next yScan
Vengono tracciati, di seguito, i parallelepipedi che costituiranno l'istogramma:
For n As Integer = nFile - 1 To 0 Step -1
For xScan As Single = 0 To CSng((numeroValori / nFile) - 1)
Dim elemento As Integer = CInt(xScan + n * (numeroValori / nFile))
If (n Mod 3) = 0 Then
DrawBox(brushGialloF, brushGialloL, brushGialloS, CInt(xScan * 10 + 12 + 3 * n), 10 + 3 * n, _
larghBarra, larghBarra, CInt(datiGrafico(elemento)))
ElseIf (n Mod 2) = 0 Then
DrawBox(brushBluF, brushBluL, brushBluS, CInt(xScan * 10 + 12 + 3 * n), 10 + 3 * n, _
larghBarra, larghBarra, CInt(datiGrafico(elemento)))
Else
DrawBox(brushRossoF, brushRossoL, brushRossoS, CInt(xScan * 10 + 12 + 3 * n), 10 + 3 * n, _
larghBarra, larghBarra, CInt(datiGrafico(elemento)))
End If
Next xScan
Next
gr.ResetTransform()
gr.ScaleTransform(scaleX, scaleY)
gr.TranslateTransform(x1, y1)
E, a questo punto, vengono inseriti la legenda ed il testo che comparirà su ciascuno dei due assi:
gr.DrawRectangle(penAssi, x2 - 25, 10, 20, 3 + nFile * 7)
For i As Integer = nFile - 1 To 0 Step -1
If (i Mod 3) = 0 Then
gr.FillRectangle(brushGialloF, x2 - 23, 13 + i * 7, 5, 4)
ElseIf (i Mod 2) = 0 Then
gr.FillRectangle(brushBluF, x2 - 23, 13 + i * 7, 5, 4)
Else
gr.FillRectangle(brushRossoF, x2 - 23, 13 + i * 7, 5, 4)
End If
Next
For xScan As Single = 0 To CSng(numeroValori / nFile * 10) Step 10
gr.DrawString(xScan.ToString, labelFont, ColoreTesto, _ CSng(bordo + xScan + 1.7 - 2 * xScan.ToString.Length), y2 - bordo + 3)
Next xScan
For yScan As Single = 0 To maxValore Step 10
gr.DrawString(yScan.ToString, labelFont, ColoreTesto, _ bordo - 2 * yScan.ToString.Length - 3, y2 - bordo - yScan)
Next yScan
For i As Integer = 1 To nFile
gr.DrawString("200" & i.ToString, labelFont, ColoreTesto, x2 - 18, 6 + 7 * i)
Next
labelFont.Dispose()
ColoreTesto.Dispose()
penAssi.Dispose()
brushBluF.Dispose()
brushBluL.Dispose()
brushBluS.Dispose()
brushRossoF.Dispose()
brushRossoS.Dispose()
brushRossoL.Dispose()
brushGialloF.Dispose()
brushGialloS.Dispose()
brushGialloL.Dispose()
gr = Nothing
End Sub
Laddove l'utente cambi ridimensioni manualmente la finestra, è opportuno che anche il grafico creato subisca la stessa azioni, mantenendo inalterata la scala:
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
Me.Refresh()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs)
End Sub
End Class
L'istogramma riportato sarà: