Link to home
Start Free TrialLog in
Avatar of NerdsOfTech
NerdsOfTechFlag for United States of America

asked on

Drawing String Characters as Points on a line graph in Visual Basic 2008 Express.

I have a line graph running, with the help from some EE experts.

Now, I would like to use String Characters such as 'X' or 'O' in my graph as points instead of rectangles.

Also, some EE experts say I should be using a class instead of what has been implemented in the code below.

500 points goes to the EE expert with the most complete answer. I will split points on improvements to the code; please include commentary on the changes.

Thanks in advance!

1 form
1 picturebox
1 label named lblL

=NerdsOfTech
Imports System.Drawing.Drawing2D
Public Class Form1
    Private GridDist As Integer = 20
    Private LPoints As New SortedList(Of Integer, Integer)
 
    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        Dim x As Integer = Math.Round(e.X / GridDist) * GridDist
        Dim y As Integer = Math.Round(e.Y / GridDist) * GridDist
        If (x / GridDist >= 1 And x / GridDist <= 11) And (y / GridDist >= 1 And y / GridDist <= 19) Then
            If (e.Button = Windows.Forms.MouseButtons.Right) Then
                If (LPoints.ContainsKey(x)) Then
                    If LPoints(x) = y Then
                        LPoints.Remove(x)
                    End If
                End If
            Else
                LPoints(x) = Math.Round(e.Y / GridDist) * GridDist
            End If
            PictureBox1.Refresh()
        End If
    End Sub
 
    Private Sub PictureBox1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.MouseLeave
        lblL.Text = ""
    End Sub
 
    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        Dim x As Integer = Math.Round(e.X / GridDist)
        Dim y As Integer = Math.Round(e.Y / GridDist)
        If (x >= 1 And x <= 11) And (y >= 1 And y <= 19) Then
            lblL.Visible = True
            lblL.Text = x & "," & y
            lblL.Left = e.X
            lblL.Top = e.Y - 5
        Else
            lblL.Visible = False
        End If
    End Sub
 
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        Dim gp As New GraphicsPath
        Dim pts As New List(Of Point)
        For Each pair In LPoints
            Dim pt As Point = New Point(pair.Key, pair.Value)
            pts.Add(pt)
            Dim rc As New Rectangle(pt.X, pt.Y, 1, 1)
            rc.Inflate(3, 3)
            gp.AddRectangle(rc)
        Next
 
        For x As Integer = 0 To (GridDist * 12) Step GridDist
            e.Graphics.DrawLine(Pens.LightBlue, x, 0, x, (GridDist * 20))
 
        Next
        For y As Integer = 0 To (GridDist * 20) Step GridDist
            e.Graphics.DrawLine(Pens.LightBlue, 0, y, (GridDist * 12), y)
        Next
 
        If LPoints.Count >= 2 Then
            e.Graphics.DrawLines(Pens.Blue, pts.ToArray)
        End If
        e.Graphics.FillPath(Brushes.Blue, gp)
        e.Graphics.DrawPath(Pens.Black, gp)
    End Sub
End Class

Open in new window

Current-progress.png
Avatar of kaufmed
kaufmed
Flag of United States of America image

I added another sorted list to keep track of which symbol a point should display. Now, if you click on the same point a second time, the symbol should change.
Imports System.Drawing.Drawing2D
Public Class Form1
    Private GridDist As Integer = 20
    Private LPoints As New SortedList(Of Integer, Integer)
    Private Symbols As New SortedList(Of Integer, String)
 
    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        Dim x As Integer = Math.Round(e.X / GridDist) * GridDist
        Dim y As Integer = Math.Round(e.Y / GridDist) * GridDist
 
        If (x / GridDist >= 1 And x / GridDist <= 11) And (y / GridDist >= 1 And y / GridDist <= 19) Then
            If (e.Button = Windows.Forms.MouseButtons.Right) Then
                If (LPoints.ContainsKey(x)) Then
                    If LPoints(x) = y Then
                        LPoints.Remove(x)
                    End If
                End If
            Else
                LPoints(x) = Math.Round(e.Y / GridDist) * GridDist
 
                If Symbols.ContainsKey(x) Then
                    If Symbols(x) = "X" Then
                        Symbols(x) = "O"
                    Else
                        Symbols(x) = "X"
                    End If
                Else
                    Symbols.Add(x, "X")
                End If
            End If
            PictureBox1.Refresh()
        End If
    End Sub
 
    Private Sub PictureBox1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.MouseLeave
        lblL.Text = ""
    End Sub
 
    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        Dim x As Integer = Math.Round(e.X / GridDist)
        Dim y As Integer = Math.Round(e.Y / GridDist)
        If (x >= 1 And x <= 11) And (y >= 1 And y <= 19) Then
            lblL.Visible = True
            lblL.Text = x & "," & y
            lblL.Left = e.X
            lblL.Top = e.Y - 5
        Else
            lblL.Visible = False
        End If
    End Sub
 
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        Dim gp As New GraphicsPath
        Dim pts As New List(Of Point)
        For Each pair In LPoints
            Dim pt As Point = New Point(pair.Key, pair.Value)
            pts.Add(pt)
            Dim rc As New Rectangle(pt.X, pt.Y, 1, 1)
            gp.AddString(Symbols(pt.X), FontFamily.GenericMonospace, FontStyle.Bold, _
                 12, New PointF(pt.X - 6, pt.Y - 6), StringFormat.GenericDefault)
        Next
 
        For x As Integer = 0 To (GridDist * 12) Step GridDist
            e.Graphics.DrawLine(Pens.LightBlue, x, 0, x, (GridDist * 20))
 
        Next
        For y As Integer = 0 To (GridDist * 20) Step GridDist
            e.Graphics.DrawLine(Pens.LightBlue, 0, y, (GridDist * 12), y)
        Next
 
        If LPoints.Count >= 2 Then
            e.Graphics.DrawLines(Pens.Blue, pts.ToArray)
        End If
        e.Graphics.FillPath(Brushes.Blue, gp)
        e.Graphics.DrawPath(Pens.Black, gp)
    End Sub
End Class

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of NerdsOfTech

ASKER

Excellent work! Thank you for the complete code example.
Glad to help :)