Baseline (The X Axis)
You can include a horizontal axis if you like the look of it. Create a new procedure named Draw3DBars.
Private Sub Draw3DBars()
g.DrawLine(New Pen(Color.Black), LeftMargin, PBBarChart.Height - BaseMargin, _
PBBarChart.Width - RightMargin, PBBarChart.Height - BaseMargin)
' Calculate length of baseline drawn by the code above
BaseLineLength = pbBarChart.Width - (LeftMargin + RightMargin)
' More code to follow
3D Bars
I came across a C# method for building up bars with a 3D effect on codeproject.com. The author, Michael Damron, had used the simple but effective idea of building a series of polygons one above the other.

Topping the bar off with a lighter coloured polygon completes the effect. So I’ve re-jigged his original basic idea for this project.
Here’s the way I’ve gone about it: The first few code items deal with some of the core calculations required. For example, we can calculate the optimum width of each bar by using the total width available and dividing it by the number of bars; not forgetting to take into account the required gaps between each bar.
Most of these are the same as were used in Part 2:
' Calculate width of each bar making full use of space available
BarWidth = CInt((BaseLineLength / SalesData.Count) - BarGap) ' Set the start point for the first bar
Dim BarStartX As Integer = LeftMargin + BarGap
' Set the baseline of the graph
Dim BaseLine As Integer = PBBarChart.Height - BaseMargin
' Calc scaling (new in this project)
VertScale = VertLineLength / HighSale
' : More code to follow
- the only new item being the VertScale variable, which is used to ensure that the bars are drawn to the correct height, allowing for the scaling we applied in the DrawVerticalAxis procedure earlier.
This procedure continues with the following block of code which draws each of the bars in turn. I have added quite a lot of commenting and (especially if you have read any of the previous articles) it should all make sense to you.
For Each gd As GraphData In SalesData
' Set the positions of the four points of the bottom-most
' parallelogram and store in an array
Dim Corners(3) As Point
Corners(0) = New Point(BarStartX, BaseLine - 10)
Corners(1) = New Point(BarStartX + BarWidth - 5, BaseLine - 10)
Corners(2) = New Point(BarStartX + BarWidth, BaseLine)
Corners(3) = New Point(BarStartX + 5, BaseLine)
' Calculate the height of this bar, taking scale into account:
Dim BarHeight As Integer = CInt(gd.Sales * VertScale)
' Create brushes to draw the bars
' Colors will change according to settings in GraphData
Dim barmainBrush As New HatchBrush(HatchStyle.Percent50, gd.BarColor)
Dim bartopBrush As New SolidBrush(gd.BarColor)
' Draw one complete bar
For i As Integer = 0 To BarHeight - 11
‘ (“BarHeight - 11” might be confusing. This makes allowance for
‘ a. the 10 pixels which are added to create the 3D depth effect
‘ plus
‘ b. the final rhombus is to be drawn in a lighter color, so we
‘ need to stop drawing these hatched ones 1 pixel below the
‘ total bar height.
' Fill next polygon using the hatchbrush
g.FillPolygon(barmainBrush, Corners)
' Move all the Y positions up the picture box by 1 pixel
Corners(0).Y -= 1
Corners(1).Y -= 1
Corners(2).Y -= 1
Corners(3).Y -= 1
Next
' Finally, top it off with a lighter rhombus
g.FillPolygon(bartopBrush, Corners)
' Move the startpoint for the next bar
BarStartX += CInt(BarWidth + BarGap)
‘ Dispose of brushes
barmainBrush.Dispose()
bartopBrush.Dispose()
Next
End Sub
(If you want to test the above procedure, don't forget to add a call to it in the btnDraw_Click event. )