I'm trying to draw multiple lines on a VB.NET PictureBox
without deleting the previous changes. If I try to draw two lines on a PictureBox
during different times with e.graphics
, then it would delete previous lines/changes.
I'm using this code on a PictureBox
's paint
event.
Public Class DrawLine
Dim point1X As Integer = 10
Dim point1Y As Integer = 10
Dim point2X As Integer = 50
Dim point2Y As Integer = 50
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
Dim pt As New Point(point1X, point1Y)
Dim pt1 As New Point(point2X, point2Y)
e.Graphics.DrawLine(Pens.Green, pt, pt1)
End Sub
End Class
This example perfectly draws a green line inside the PictureBox
.
However, when I have a button that draws another line on the PictureBox
after the form has already been painted, the previous line drawn disappears.
For example, if I have a function like this that draws another line
Private Function DrawAnotherLine(xPos1 As Integer, yPos1 As Integer, xPos2 As Integer, yPos2 As Integer)
point1X = xPos1
point1Y = yPos1
point2X = xPos2
point2Y = yPos2
PictureBox1.Invalidate()
End Function
It deletes the first line drawn and only draws the second line. I want it draw the second line on top of the first line and not just delete the first line though, how would I do this?
(Note: I cannot include drawing the first line in the function, as this function will be used multiple times on top of the lines its already drawn).
GDI+ drawing is pretty simple:
Paint
event of the control you want to draw on.Invalidate
on the control.If you want to be able to draw multiple lines then you first need a data structure that represents a single line and then somewhere to store multiple instances of that data structure. The most obvious way to do that is to define a class or structure that contains the data for a single line, e.g.
Public Class Line
Public ReadOnly Property StartPoint As Point
Public ReadOnly Property EndPoint As Point
Public Sub New(startPoint As Point, endPoint As Point)
Me.StartPoint = startPoint
Me.EndPoint = endPoint
End Sub
End Class
and to then declare a field that refers to a collection of that type:
Private lines As New List(Of Line)
Your Paint
event handler then draws all the lines in the collection:
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
For Each line In lines
e.Graphics.DrawLine(Pens.Black, line.StartPoint, line.EndPoint)
Next
End Sub
To draw a new line, you add a new Line
object to the collection and Invalidate
the control:
Private Sub AddNewLine(startPoint As Point, endPoint As Point)
lines.Add(New Line(startPoint, endPoint))
PictureBox1.Invalidate()
End Sub
How you get those points is up to you. You might record the location on a MouseDown
event and then call AddNewLine
on a MouseUp
event or you might do something else entirely.
It is also preferable to specify the smallest area possible when calling Invalidate
, but that's beyond the scope of this question.