📄 bargraph.vb
字号:
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.Drawing.Imaging
Imports System.Drawing.Drawing2D
Namespace ComponenteGrafico
'*********************************************************************
'
' BarGraph Class
'
' This class uses GDI+ to render Bar Chart.
'
'*********************************************************************
Public Class BarGraph
Inherits Chart
Private _graphLegendSpacer As Single = 15.0F
Private _labelFontSize As Integer = 7
Private _legendFontSize As Integer = 9
Private _legendRectangleSize As Single = 10.0F
Private _spacer As Single = 5.0F
' Overall related members
Private _backColor As Color
Private _fontFamily As String
Private _longestTickValue As String = String.Empty ' Used to calculate max value width
Private _maxTickValueWidth As Single ' Used to calculate left offset of bar graph
Private _totalHeight As Single
Private _totalWidth As Single
' Graph related members
Private _barWidth As Single
Private _bottomBuffer As Single ' Space from bottom to x axis
Private _displayBarData As Boolean
Private _fontColor As Color
Private _graphHeight As Single
Private _graphWidth As Single
Private _maxValue As Single = 0.0F ' = final tick value * tick count
Private _scaleFactor As Single ' = _maxValue / _graphHeight
Private _spaceBtwBars As Single ' For now same as _barWidth
Private _topBuffer As Single ' Space from top to the top of y axis
Private _xOrigin As Single ' x position where graph starts drawing
Private _yOrigin As Single ' y position where graph starts drawing
Private _yLabel As String
Private _yTickCount As Integer
Private _yTickValue As Single ' Value for each tick = _maxValue/_yTickCount
' Legend related members
Private _displayLegend As Boolean
Private _legendWidth As Single
Private _longestLabel As String = String.Empty ' Used to calculate legend width
Private _maxLabelWidth As Single = 0.0F
Public Property FontFamily() As String
Get
Return _fontFamily
End Get
Set(ByVal Value As String)
_fontFamily = Value
End Set
End Property
Public WriteOnly Property BackgroundColor() As Color
Set(ByVal Value As Color)
_backColor = Value
End Set
End Property
Public WriteOnly Property BottomBuffer() As Integer
Set(ByVal Value As Integer)
_bottomBuffer = Convert.ToSingle(Value)
End Set
End Property
Public WriteOnly Property FontColor() As Color
Set(ByVal Value As Color)
_fontColor = Value
End Set
End Property
Public Property Height() As Integer
Get
Return Convert.ToInt32(_totalHeight)
End Get
Set(ByVal Value As Integer)
_totalHeight = Convert.ToSingle(Value)
End Set
End Property
Public Property Width() As Integer
Get
Return Convert.ToInt32(_totalWidth)
End Get
Set(ByVal Value As Integer)
_totalWidth = Convert.ToSingle(Value)
End Set
End Property
Public Property ShowLegend() As Boolean
Get
Return _displayLegend
End Get
Set(ByVal Value As Boolean)
_displayLegend = Value
End Set
End Property
Public Property ShowData() As Boolean
Get
Return _displayBarData
End Get
Set(ByVal Value As Boolean)
_displayBarData = Value
End Set
End Property
Public WriteOnly Property TopBuffer() As Integer
Set(ByVal Value As Integer)
_topBuffer = Convert.ToSingle(Value)
End Set
End Property
Public Property VerticalLabel() As String
Get
Return _yLabel
End Get
Set(ByVal Value As String)
_yLabel = Value
End Set
End Property
Public Property VerticalTickCount() As Integer
Get
Return _yTickCount
End Get
Set(ByVal Value As Integer)
_yTickCount = Value
End Set
End Property
Public Sub New()
AssignDefaultSettings()
End Sub 'New
Public Sub New(ByVal bgColor As Color)
AssignDefaultSettings()
BackgroundColor = bgColor
End Sub 'New
'*********************************************************************
'
' This method collects all data points and calculate all the necessary dimensions
' to draw the bar graph. It is the method called before invoking the Draw() method.
' labels is the x values.
' values is the y values.
'
'*********************************************************************
Public Overloads Sub CollectDataPoints(ByVal labels() As String, ByVal values() As String)
If labels.Length = values.Length Then
Dim i As Integer
For i = 0 To labels.Length - 1
Dim temp As Single = Convert.ToSingle(values(i))
Dim shortLbl As String = MakeShortLabel(labels(i))
' For now put 0.0 for start position and sweep size
DataPoints.Add(New ChartItem(shortLbl, labels(i), temp, 0.0F, 0.0F, GetColor(i)))
' Find max value from data; this is only temporary _maxValue
If _maxValue < temp Then
_maxValue = temp
End If
' Find the longest description
If _displayLegend Then
Dim currentLbl As String = labels(i) + " (" + shortLbl + ")"
Dim currentWidth As Single = CalculateImgFontWidth(currentLbl, _legendFontSize, FontFamily)
If _maxLabelWidth < currentWidth Then
_longestLabel = currentLbl
_maxLabelWidth = currentWidth
End If
End If
Next i
CalculateTickAndMax()
CalculateGraphDimension()
CalculateBarWidth(DataPoints.Count, _graphWidth)
CalculateSweepValues()
Else
Throw New Exception("X data count is different from Y data count")
End If
End Sub 'CollectDataPoints
'*********************************************************************
'
' Same as above; called when user doesn't care about the x values
'
'*********************************************************************
Public Overloads Sub CollectDataPoints(ByVal values() As String)
Dim labels As String() = values
CollectDataPoints(labels, values)
End Sub 'CollectDataPoints
'*********************************************************************
'
' This method returns a bar graph bitmap to the calling function. It is called after
' all dimensions and data points are calculated.
'
'*********************************************************************
Public Overrides Function Draw() As Bitmap
Dim height As Integer = Convert.ToInt32(_totalHeight)
Dim width As Integer = Convert.ToInt32(_totalWidth)
Dim bmp As New Bitmap(width, height)
Dim graph As Graphics = Nothing
Try
graph = Graphics.FromImage(bmp)
graph.CompositingQuality = CompositingQuality.HighQuality
graph.SmoothingMode = SmoothingMode.AntiAlias
' Set the background: need to draw one pixel larger than the bitmap to cover all area
graph.FillRectangle(New SolidBrush(_backColor), -1, -1, bmp.Width + 1, bmp.Height + 1)
DrawVerticalLabelArea(graph)
DrawBars(graph)
DrawXLabelArea(graph)
If _displayLegend Then
DrawLegend(graph)
End If
Finally
If Not (graph Is Nothing) Then
graph.Dispose()
End If
End Try
Return bmp
End Function 'Draw
'*********************************************************************
'
' This method draws all the bars for the graph.
'
'*********************************************************************
Private Sub DrawBars(ByVal graph As Graphics)
Dim brsFont As SolidBrush = Nothing
Dim valFont As Font = Nothing
Dim sfFormat As StringFormat = Nothing
Try
brsFont = New SolidBrush(_fontColor)
valFont = New Font(_fontFamily, _labelFontSize)
sfFormat = New StringFormat
sfFormat.Alignment = StringAlignment.Center
Dim i As Integer = 0
' Draw bars and the value above each bar
Dim item As ChartItem
For Each item In DataPoints
Dim barBrush As SolidBrush = Nothing
Try
barBrush = New SolidBrush(item.ItemColor)
Dim itemY As Single = _yOrigin + _graphHeight - item.SweepSize
' When drawing, all position is relative to (_xOrigin, _yOrigin)
graph.FillRectangle(barBrush, _xOrigin + item.StartPos, itemY, _barWidth, item.SweepSize)
' Draw data value
If _displayBarData Then
Dim startX As Single = _xOrigin + i * (_barWidth + _spaceBtwBars) ' This draws the value on center of the bar
Dim startY As Single = itemY - 2.0F - valFont.Height ' Positioned on top of each bar by 2 pixels
Dim recVal As New RectangleF(startX, startY, _barWidth + _spaceBtwBars, valFont.Height)
graph.DrawString(item.Value.ToString("#,###.##"), valFont, brsFont, recVal, sfFormat)
End If
i += 1
Finally
If Not (barBrush Is Nothing) Then
barBrush.Dispose()
End If
End Try
Next item
Finally
If Not (brsFont Is Nothing) Then
brsFont.Dispose()
End If
If Not (valFont Is Nothing) Then
valFont.Dispose()
End If
If Not (sfFormat Is Nothing) Then
sfFormat.Dispose()
End If
End Try
End Sub 'DrawBars
'*********************************************************************
'
' This method draws the y label, tick marks, tick values, and the y axis.
'
'*********************************************************************
Private Sub DrawVerticalLabelArea(ByVal graph As Graphics)
Dim lblFont As Font = Nothing
Dim brs As SolidBrush = Nothing
Dim lblFormat As StringFormat = Nothing
Dim pen As Pen = Nothing
Dim sfVLabel As StringFormat = Nothing
Try
lblFont = New Font(_fontFamily, _labelFontSize)
brs = New SolidBrush(_fontColor)
lblFormat = New StringFormat
pen = New Pen(_fontColor)
sfVLabel = New StringFormat
lblFormat.Alignment = StringAlignment.Near
' Draw vertical label at the top of y-axis and place it in the middle top of y-axis
Dim recVLabel As New RectangleF(0.0F, _yOrigin - 2 * _spacer - lblFont.Height, _xOrigin * 2, lblFont.Height)
sfVLabel.Alignment = StringAlignment.Center
graph.DrawString(_yLabel, lblFont, brs, recVLabel, sfVLabel)
' Draw all tick values and tick marks
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -