VB.NET Trying to draw a line - vb.net

I am creating a program where the user can command a turtle which moves around on a a white panel named panel 1. I have made the turtle rotate usingrotatefliptype
I am now in the process of making a line follow behind it. I've had a few ideas including placing pixels in places that meet the requirement. My one problem is the location. Is it possible to make the location relative to a certain point?
My current code is:
Sub imageCloner(clonedImage As Image, clonedWidth As Int16, clonedHeight As Int16, clonedLocation As Point)
'clone image
Dim dotImage As New PictureBox()
dotImage.Image = clonedImage
dotImage.Location = clonedLocation
dotImage.Width = clonedWidth
dotImage.Height = clonedHeight
dotImage.SizeMode = picBoxTurtle.SizeMode
panel1.Controls.Add(dotImage)
End Sub
Sub findGradient()
'gradient = rise / run
turtleMovementGradient = (turtleYLocation - turtleOriginalYLocation) / (turtleXLocation - turtleOriginalXLocation)
End Sub
Sub drawLine()
find the gradient
findGradient()
create variables
Dim xcounter As Int16 = 0
Dim ycounter As Int16 = 0
For ycounter = 1 To panel1.Height
For xcounter = 1 To panel1.Width
If ycounter / xcounter = turtleMovementGradient Then
imageCloner(blackDotOnePixel.Image, 1, 1, New Point(panel1.Width - xcounter, panel1.Height - ycounter))
End If
Next
Next
End Sub
The drawLine() subroutine is run first.
I NEED HELP WITH THE DRAWING OF THE LINE

This should give you some idea.
Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
' Create a local version of the graphics object for the Panel.
Dim g As Graphics = e.Graphics
' Draw a string on the Panel.
g.DrawString("This is a diagonal line drawn on the control", New Font("Arial", 10), Brushes.Red, New PointF(30.0F, 30.0F))
' Draw a line in the Panel.
g.DrawLine(System.Drawing.Pens.Red, Panel11.Left, Panel1.Top, Panel1.Right, Panel1.Bottom)
End Sub

Related

Random picturebox arrangement

I am new to visual basics and was wondering how to do the following program: I have 9 picture boxes and a button "arrange". For my program, I would like that all picture boxes come together like a puzzle randomly to make a square that has a width and height of three picture boxes. The square made would have all nine picture boxes in one and every time you click the button "arrange" the picture boxes would change to a random location within the square. So far, I have written so that all the picture boxes become the same size but i don't know how to make them come together in a square. Thanks in advance.
Public Class frm1
Dim Placement As Integer
Private Sub btnArrange_Click(sender As Object, e As EventArgs) Handles btnArrange.Click
picDeux.Size = picgris.Size
picTrois.Size = picgris.Size
picQuatre.Size = picgris.Size
picCinq.Size = picgris.Size
picSix.Size = picgris.Size
picSept.Size = picgris.Size
picHuit.Size = picgris.Size
picNeuf.Size = picgris.Size
lstNum.Items.Clear()
For i = 1 To 3
For j = 1 To 3
Dim L As New Point(picgris.Width * j + 100, picgris.Height * i)
lstNum.Items.Add(L)
Next
Next
For i = 1 To 3
For j = 1 To 3
Placement = Int(Rnd() * (lstNum.Items.Count))
Next
Next
End Sub
End Class
I created nine pictures boxes at design time. You would assign a different image to each picture box. They are all square and the same size. Mine are 100 x 100 to make the arithmetic easy.
I made an array of points as a form level variable. These point will form a 300 x 300 square with the picture boxes. I also declared an array of PictureBox. In the Form.Load I added the pictures boxes to the array.
To reposition the picture boxes assigned the array to a list. Items in this list will be removed because we don't want to assign the same location to more the one picture box. This will not effect the original array.
Looping through the picture boxes we assign a random position to the box then remove that point from the list.
Public Class PictureSort
Private Rand As New Random()
Private PointArray As Point() = {New Point(100, 100), New Point(200, 100), New Point(300, 100), New Point(100, 200), New Point(200, 200), New Point(300, 200), New Point(100, 300), New Point(200, 300), New Point(300, 300)}
Private PictureBoxArray(8) As PictureBox
Private Sub PictureSort_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PictureBoxArray = {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9}
End Sub
Private Sub RepositionPictureBoxes()
Dim lst = PointArray.ToList
For Each pb In PictureBoxArray
Dim index = Rand.Next(0, lst.Count)
pb.Location = lst(index)
lst.RemoveAt(index)
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
RepositionPictureBoxes()
End Sub
End Class
My advice is to use a control array - you have an example here that should help: VB.NET Control Array- Declaration and Application.
You just need to initiate that array of controls once, this can be done at form load.
The next step is to sort that array in a random manner. Finally, loop on the array and every time your current loop index modulo 3 = 0, then you increase the Y coordinates and reset the X position.
Here is an example. You can see that each time you click on the button, the picture boxes are rearranged on the form in random order using an ad hoc function. For each picture box, a bitmap is generated on the fly to show the index of the control.. this is for demonstration purposes.
Public Class frmPics
Private pics As New List(Of PictureBox)
Private Const picture_width As Integer = 100, picture_height As Integer = 50
Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
' instantiate controls
Dim font As New Font("Arial", 20, FontStyle.Regular, GraphicsUnit.Pixel)
For i As Integer = 1 To 9
Dim pic As New PictureBox
pic.Visible = False
pic.Name = "pic" & i
pic.Text = i.ToString
Console.WriteLine("Create control: name: " & pic.Name)
' generate an ad-hoc bitmap image showing the index of the control
Dim bitmap As New Bitmap(picture_width, picture_height)
Using g As Graphics = Graphics.FromImage(bitmap)
Dim width As Integer = CInt(g.MeasureString(Text, font).Width)
Dim height As Integer = CInt(g.MeasureString(Text, font).Height)
End Using
Using g As Graphics = Graphics.FromImage(bitmap)
g.Clear(Color.Blue)
g.DrawString(i.ToString, font, New SolidBrush(Color.White), 0, 0)
End Using
pic.Image = bitmap
pics.Add(pic)
Me.Controls.Add(pic)
Next
End Sub
Private Sub btnShuffle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShuffle.Click
Dim x As Integer = 10, y As Integer = picture_height
Dim counter As Integer = 1
Dim rnd As New Random()
' show controls on form
Console.WriteLine("Show controls on form")
Me.SuspendLayout()
For Each item In pics.OrderBy(Function() rnd.Next)
item.Width = picture_width
item.Height = picture_height
item.Location = New Point(x, y)
item.BorderStyle = BorderStyle.FixedSingle
item.Visible = True
Console.WriteLine("counter: " & counter & " - control name" & item.Name & " - position: " & item.Location.X & "/" & item.Location.Y & " text: " & item.Text)
' reset X position every 3 iterations
If counter Mod 3 = 0 Then
x = 10
y += item.Height
Else
x += item.Width
End If
counter += 1
Next
Me.ResumeLayout()
End Sub
End Class

Take a photo every 5 seconds

I am developing a panel, which from time to time runs a process and generates an image within it. Once the image is generated, you need to take a photo to save it for the changes that are made.
I already developed the part where the images change, but when I take the photos, they all come out blank. Add a delay on the screen thinking that it should take a while to take the photo of the panel later, but it still comes out blank and if there is something inside the panel, since I am resizing it according to the size of what is updated.
Can you help me to see where my error is? Or guide me to obtain an optimal result?, I also tried using a timer, but it gives me the same result, any ideas?
This is the code developed.
sub buldimages()
Panel1.Refresh()
System.Threading.Thread.Sleep(5000)
segondGa(varName)
'Timer1.Start()
End Sub
Function segondGa(nameLine As String)
Dim widthOldPuno = Panel1.Width
Dim heightOldPuno = Panel1.Height
Dim widthOldPdos = Panel2.Width
Dim heightOldPdos = Panel2.Height
Dim coordenada, i As Integer
For Each obj As Control In Panel1.Controls
coordenada = obj.Location.X
Next
Panel1.Width = widthOldPuno + (coordenada - Panel1.Width)
Panel2.Width = Panel1.Width + 113
Panel2.Height = heightOldPdos - 65
Dim nameLineB As String = nameLine
Using bmp = New Bitmap(Panel2.Width, Panel2.Height)
Panel2.DrawToBitmap(bmp, New Rectangle(0, 0, bmp.Width, bmp.Height))
Dim bmp2 As New Bitmap(bmp.Width * 3, bmp.Height * 3)
Dim gr As Graphics = Graphics.FromImage(bmp2)
gr.DrawImage(bmp, New Rectangle(0, 0, bmp2.Width, bmp2.Height))
bmp2.Save("C:\TEMP\" & nameLineB & ".png")
End Using
Panel2.Width = widthOldPdos
Panel2.Height = heightOldPdos
Panel1.Width = widthOldPuno
End Function
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim seconds As Integer
Label1.Text = seconds + 1
If Label1.Text = "5" Then
Timer1.Stop()
End If
End Sub

Is it possible to group multiple PictureBoxes?

I can drag a PictureBox onto a Form Control, a Tab Control or a Panel Control, etc. And I can import an image into a PictureBox. However, I don't know how to group multiple PictureBoxes together in Visual Studio 2017. Looks like there is no such a function. I need this function because I want to generate a big picture based on the user's input. That big picture consists of multiple small pictures, the visibility of which is controlled by the user through multiple checkboxes.
In Excel, I could put multiple pictures in it, group them together, use the VBA to control the visibility of each picture, and finally copy that picture group into a Word file. I would do this in a VSTO Word Document project in Visual Studio 2017 using vb.net.
I added some pictures for demonstrate the expected function.
Picture 1 shows the small pictures to be used in a big picture. (Please ignore the .vslx file)
Picture 2 shows a possible result based on user's input.
You can make your own custom control. here is an example/suggestion how to do it with a User control that can be reused across your application. the user control is holding panels in a matrix, you can set a drag&drop Event to each Panel control and the user will be able to drop a picture box on each panel:
USER CONTROL:
Public Class UserControl1
Public NumberOfPanelsInRow As Integer
Sub New(ByVal height As Integer, width As Integer, Optional ByVal numberofPanelsInRow As Integer = 3)
' This call is required by the designer.'
InitializeComponent()
' Add any initialization after the InitializeComponent() call.'
Me.Height = height
Me.Width = width
Me.NumberOfPanelsInRow = numberofPanelsInRow
End Sub
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' grouped panels to hold picturebox you can drag & drop to them...'
Dim panelHeight As Integer = Me.Height / NumberOfPanelsInRow
Dim panelWidth As Integer = Me.Width / NumberOfPanelsInRow
Dim colors() As Color = {Color.Pink, Color.Black, Color.Red, Color.Cyan, Color.Green, Color.Orange,
Color.Red, Color.Pink, Color.Black, Color.Red, Color.Cyan, Color.Green, Color.Orange, Color.Red}
Dim total As Integer = NumberOfPanelsInRow * NumberOfPanelsInRow
Dim currentYlocation As Integer = 0
Dim currentXlocation As Integer = 0
Dim location As Point = New Point(0, currentYlocation)
Dim rowcounter As Integer = 0
Dim itemcounter As Integer = 0
For i = 1 To total
If rowcounter >= NumberOfPanelsInRow Then
rowcounter = 0
currentYlocation += panelHeight
currentXlocation = 0
End If
' to each one of this panel you can drag a picture box'
Dim p As New Panel
p.Size = New Size(panelWidth, panelHeight)
p.Location = New Point(currentXlocation, currentYlocation)
p.BackColor = colors(itemcounter)
Me.Controls.Add(p)
rowcounter += 1
itemcounter += 1
currentXlocation += panelWidth
Next
End Sub
End Class
CALLING THE USER CONTROL FROM FORM1:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim uc = New UserControl1(300, 300)
Me.Controls.Add(uc)
End Sub
End Class
GUI OUTPUT:

System.ArgumentException: Parameter is not valid. When entering a value in a text box

I'm trying to create a simple program that will allow you to enter a degree and have a dial fill to that exact degree, and then also display the degree inside of the dial. The project builds without errors, and will display correctly until a value is entered into the textbox, and then I will get the error on the line
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
If I comment out that line it will go down to the line below it. This is my first time using vb.net, so I'm guessing there is something small I'm just doing incorrectly. My full code is:
Public Class Form1
Dim degree As Double
Dim ge As Graphics
Private Sub Form2_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
ge = e.Graphics
DrawProgress(ge, New Rectangle(150, 25, 400, 400), degree)
End Sub
Private Sub DrawProgress(g As Graphics, rect As Rectangle, degree As Double)
'work out the angles for each arc
Dim progressAngle = CSng(degree)
Dim remainderAngle = 360 - progressAngle
'create pens to use for the arcs
Using progressPen As New Pen(Color.LightSeaGreen, 2), remainderPen As New Pen(Color.LightGray, 2)
'set the smoothing to high quality for better output
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
'draw the blue and white arcs
g.DrawArc(progressPen, rect, -90, progressAngle)
g.DrawArc(remainderPen, rect, progressAngle - 90, remainderAngle)
End Using
'draw the text in the centre by working out how big it is and adjusting the co-ordinates accordingly
Using fnt As New Font(Me.Font.FontFamily, 50)
Dim text As String = degree.ToString
Dim textSize = g.MeasureString(text, fnt)
Dim textPoint As New Point(CInt(rect.Left + (rect.Width / 2) - (textSize.Width / 2)), CInt(rect.Top + (rect.Height / 2) - (textSize.Height / 2)))
'now we have all the values draw the text
g.DrawString(text, fnt, Brushes.Black, textPoint)
End Using
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Dim input_s As String
input_s = TextBox1.Text
If (String.IsNullOrEmpty(input_s)) Then
degree = 0
Else
degree = CDec(input_s)
End If
DrawProgress(ge, New Rectangle(150, 25, 400, 400), degree)
End Sub
End Class

Determining what objects fall within a selection rectangle (marquee)

I'm writing a program that (amongst other things) provides an IDE-like environment for the user where they can select one or more objects with a rectangualr selection tool.
All selections will be a simple rectangle, and all selectable objects will be simple rectangles as well.
I already have the code (VB.Net) to create the rubber-banding effect visually - what I need is an efficient algorithm that will tell me what objects have at least a portion of their area within the final selection rectangle.
If it helps to visualize, what I want to do would be identical to dragging a selection box over icons on the Windows desktop... whichever icons have even a portion of their areas located within that selection marquee are highlighted (selected).
Any help would be appreciated... thank you in advance
Dim Rect1 As New Rectangle(10, 10, 20, 20)
Dim Rect2 As New Rectangle(5, 5, 20, 20)
Debug.Print(Rect1.IntersectsWith(Rect2))
IntersectsWith works as BigFunger already has mentioned. But aditionally you should check if a rectangle contains another rectangle(intersectsWith only checks for intersection).
A small sample-form that demonstrates it:
Public Class SelectionRectangle
Private first As Point
Private allRectangles As New List(Of RectangleF)
Private Sub form_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseDown
first = New Point(e.X, e.Y)
End Sub
Private Sub form_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseUp
Dim p As New Pen(Brushes.Black, 2)
Dim g As Graphics
Dim second As New Point(e.X, e.Y)
Dim x, y, w, h As Int32
x = DirectCast(IIf(first.X > second.X, second.X, first.X), Int32)
y = DirectCast(IIf(first.Y > second.Y, second.Y, first.Y), Int32)
w = Math.Abs(second.X - first.X)
h = Math.Abs(second.Y - first.Y)
Dim nextRec As New RectangleF(x, y, w, h)
Dim intersects As Boolean = False
For Each rec As RectangleF In allRectangles
If rec.Contains(nextRec) OrElse rec.IntersectsWith(nextRec) Then
intersects = True
Exit For
End If
Next
If Not intersects Then
p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot
g = Me.CreateGraphics()
g.DrawLine(p, first.X, first.Y, second.X, first.Y)
g.DrawLine(p, second.X, second.Y, first.X, second.Y)
g.DrawLine(p, first.X, first.Y, first.X, second.Y)
g.DrawLine(p, second.X, second.Y, second.X, first.Y)
allRectangles.Add(nextRec)
Else
Beep()
End If
End Sub
End Class
UPDATE: changed this code to 1.first check in both directions and 2. and more important for you: checks also if one rectangle not only intersects another but additionally if it contains another.