Graphics question - building controls...

mandelbrot

Centurion
Joined
Jul 1, 2005
Messages
194
Location
UK North East
Hi All,


I've written a control which displays information from a specific class in a similar (but not the same) manner as a TreeView. Originally I started by drawing out the control in the same way that I would with a webpage, but found this exceptionally slow. Now, I've loaded all data into memory, and run through the tree structure reading the appropriate data from the nested classes and drawing to screen using graphics methods. This should be much faster, but I'm getting no results...

Here's the basic drawing routines - I'd appreciate any help I can get...
Visual Basic:
    'Draw the tree...
    Private Sub DrawTree(ByVal pOccurence As Occurence, ByVal pGraphics As Graphics)
        'Dimensions...
        Dim currPen As New Pen(_EventColor, 2)
        Dim currSize As Size
        Dim bracketT As Integer = -1
        Dim bracketB As Integer = -1
        Dim bracketL As Integer = -1
        Dim bracketR As Integer = -1
        Dim drawPoints(3) As Point
        'Initialise...
        If Not isDrawing Then
            linePointer = 0
            pGraphics.Clear(Me.BackColor)
            Controls.Clear()
            clickZones.Clear()
        End If
        isDrawing = True
        'Draw the starting text...
        DrawText("Started: " & pOccurence.Started.ToString("HH:mm") & " - [" & pOccurence.Type.Name & "] " & pOccurence.Title, pOccurence, pGraphics)
        DrawText(pOccurence.Description, pOccurence, pGraphics)
        'Check for and draw children...
        If pOccurence.Count > 0 Then
            Dim currOcc As Occurence
            For Each currOcc In pOccurence
                DrawTree(currOcc, pGraphics)
            Next
        End If
        'Draw the end text of the class...
        If pOccurence.Ended = Util.defaultDate Then
            DrawText("Still active...", pOccurence, pGraphics)
        Else
            DrawText("Ended: " & pOccurence.Ended.ToString("HH:mm"), pOccurence, pGraphics)
        End If
        'Draw the bracket...
        bracketT = CType(linePointer * ySize + ySize / 2, Integer)
        bracketB = CType(linePointer * ySize + ySize / 2, Integer)
        bracketL = CType(pOccurence.NodeLevel * xSize + xSize / 4, Integer)
        bracketR = CType(bracketL + xSize / 2, Integer)
        drawPoints(0) = New Point(bracketR, bracketT)
        drawPoints(1) = New Point(bracketL, bracketT)
        drawPoints(2) = New Point(bracketL, bracketB)
        drawPoints(3) = New Point(bracketR, bracketB)
        'Check to see if the current occurence is selected...
        If _Value Is pOccurence Then
            currPen.Color = _HighlightColor
            pGraphics.DrawRectangle(currPen, New Rectangle(bracketL - 4, bracketT - 4, bracketR + 4, bracketB + 4))
        End If
        'Check which color we should be using...
        Select Case pOccurence.Class.Name
            Case "Event"
                currPen.Color = _EventColor
            Case "Action"
                currPen.Color = _ActionColor
            Case "Causality"
                currPen.Color = _CausalityColor
        End Select
        pGraphics.DrawLines(currPen, drawPoints)
        clickZones.Add(New Zone(pOccurence, bracketL - 4, bracketT - 4, bracketR + 4, bracketB + 4))
        'Close out...
        isDrawing = False
    End Sub
    
    'Draw the text...
    Private Sub DrawText(ByVal pText As String, ByVal pOccurence As Occurence, ByVal pGraphics As Graphics)
        'Dimensions...
        Dim currpen As New Pen(_HighlightColor)
        Dim currSize As SizeF = pGraphics.MeasureString(pText, Me.Font)
        Dim currBrush As New Drawing.SolidBrush(_EventColor)
        Dim currRegion As New Rectangle(CType(pOccurence.NodeLevel * xSize, Integer), _
                                        CType(linePointer * ySize, Integer), _
                                        CType(currSize.Width, Integer), _
                                        CType(currSize.Height, Integer))
        'Check to see if the current occurence is selected...
        If _Value Is pOccurence Then
            currPen.Color = _HighlightColor
            pGraphics.DrawRectangle(currpen, currRegion)
        End If
        'Check which color we should be using...
        Select Case pOccurence.Class.Name
            Case "Event"
                currBrush.Color = _EventColor
            Case "Action"
                currBrush.Color = _ActionColor
            Case "Causality"
                currBrush.Color = _CausalityColor
        End Select
        'Draw the start of the object...
        pGraphics.DrawString(pText, Me.Font, currBrush, pOccurence.NodeLevel * xSize, linePointer * ySize)
        clickZones.Add(New Zone(currRegion, pOccurence))
        'Increment the line counter...
        linePointer += 1
    End Sub
Just while I think on - the DrawTree routine is initially called from the Invalidate routine; pGraphics being set to Me.CreateGraphics, and disposed on the line after the call...
Visual Basic:
    'Invalidate the current control...
    Public Overloads Sub Invalidate()
        Me.Invalidate(New Rectangle(0, 0, Me.Width, Me.Height))
        If Not _StartOfDay Is Nothing Then
            Dim pageGfx As Graphics = Me.CreateGraphics
            DrawTree(_StartOfDay, pageGfx)
            pageGfx.Dispose()
        End If
    End Sub

Thanks in advance,
Paul.
 
Last edited:
I don't have a direct answer to your question but you need to realize that the Graphics class is a bit slower than GDI. This is particularly applicable with blitting functions, especially when many small images are drawn, as opposed to a few large images.

Depending on your exact needs you might want to consider moving to GDI or double buffering your control.
 
Thanks for your response, marble. I'm not so worried about the speed - I used to draw the screen using controls (i.e. image controls and labels), which is very slow! I'm having to revert to this until I can figure out the graphics side of things.

The idea behind the routines above is that it reads the tree using a recursive function call and drawing all the appropriate text, but only draws the brackets in (literally looking like a square bracket [ ) as the recurssion unwraps.

The image attached shows what I'm trying to achieve (this is a working image from the current implementation).


Paul.
 

Attachments

Last edited:
Back
Top