Drawing circles on the form using e.graphics.drawellips? - vb.net-2010

I want to draw circles within circles and i have tried this but having difficulties
here is my code
Private Sub DrawCircle()
Dim g As Graphics
g = Panel1.CreateGraphics
Dim yellowPen As New Pen(Color.Yellow, 20)
Dim bluePen As New Pen(Color.Blue, 30)
Dim greenPen As New Pen(Color.Green, 20)
Dim skybluePen As New Pen(Color.AliceBlue, 20)
Dim voiletPen As New Pen(Color.Violet, 15)
Dim blackPen As New Pen(Color.Black, 2)
' Draw ellipses
g.DrawEllipse(yellowPen, 260, 180, 10, 10)
g.DrawEllipse(greenPen, 240, 160, 50, 50)
g.DrawEllipse(bluePen, 220, 140, 90, 90)
g.DrawEllipse(greenPen, 200, 120, 130, 130)
g.DrawEllipse(skybluePen, 180, 100, 170, 170)
g.DrawEllipse(blackPen, 180, 100, 170, 170)
g.DrawEllipse(voiletPen, 170, 90, 190, 190)
End Sub
Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
DrawCircle()
End Sub
It is working well but if there is any other option because if you change a little in this code everything goes wrong please help me out

May be i did't get your point right and i think you are looking for an alternate solution
here is one
Private colorForAllCircles As Color
Private ReadOnly rand As New Random
Function RandomColor() As Color
Return Color.FromArgb(rand.Next(0, 256), rand.Next(0, 256), rand.Next(0, 256))
End Function
Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
Dim centerX, centerY As Integer
Dim cornerX, cornerY As Integer
Dim radius As Integer
Dim greenPen As New Pen(Brushes.Blue)
centerX = 300
centerY = 200
Dim i As Integer
For i = 20To 200 Step 20
greenPen = New Pen(RandomColor, 20)
radius = i
cornerX = centerX - radius / 2
cornerY = centerY - radius / 2
e.Graphics.DrawEllipse(greenPen, cornerX, cornerY, radius, radius)
Next
End Sub

Related

Use bottom-sx corner as pivot while performing RotateTransform

I know how to rotate a text or a rectangle using the top-sx corner as pivot. For example:
Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
Dim g As Graphics = Panel1.CreateGraphics()
Dim font As Font = New Font("Arial", 42, FontStyle.Regular, GraphicsUnit.Pixel)
Dim i As Single
For i = 0 To 255 Step 30
Dim myBrush As SolidBrush = New SolidBrush(Color.FromArgb(255, i, 255 - i, i)) 'Green to violet
'Draw a string and a Rectangle of the same size
Dim stringSize As SizeF = g.MeasureString("Hello", font)
g.TranslateTransform(200, 200)
g.RotateTransform(-i)
g.DrawString("Hello", font, myBrush, 0, 0)
g.DrawRectangle(New Pen(Color.FromArgb(50, 255, 0, 0), 1), 0, 0, stringSize.Width, stringSize.Height)
g.ResetTransform()
myBrush.Dispose()
Next
'Draw the center of the rotation
g.DrawRectangle(Pens.Black, 200 - 5, 200 - 5, 10, 10)
g.Dispose()
End Sub
With this code I have the following output:
How can I rotate my graphic elements by using the bottom-sx corner as pivot?
Replace as follows:
Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
Dim g As Graphics = Panel1.CreateGraphics()
Dim font As Font = New Font("Arial", 42, FontStyle.Regular, GraphicsUnit.Pixel)
Dim i As Single
For i = 0 To 255 Step 30
Dim myBrush As SolidBrush = New SolidBrush(Color.FromArgb(255, CInt(i), CInt(255 - i), CInt(i))) 'Green to violet
'Draw a string and a Rectangle of the same size
Dim stringSize As SizeF = g.MeasureString("Hello", font)
g.TranslateTransform(200, 200)
g.RotateTransform(-i)
Dim coorX As Single = 0
Dim coorY As Single = -stringSize.Height
g.DrawString("Hello", font, myBrush, coorX, coorY)
g.DrawRectangle(New Pen(Color.FromArgb(50, 255, 0, 0), 1), coorX, coorY, stringSize.Width, stringSize.Height)
g.ResetTransform()
myBrush.Dispose()
Next
'Draw the center of the rotation
g.DrawRectangle(Pens.Black, 200 - 5, 200 - 5, 10, 10)
g.Dispose()
End Sub
And here the same version optimized as Memory and Code Friendly:
Private Sub Panel1_Click(sender As Object, e As EventArgs) Handles Panel1.Click
Using g As Graphics = Panel1.CreateGraphics()
Using font As Font = New Font("Arial", 42, FontStyle.Regular, GraphicsUnit.Pixel)
'Draw a string and a Rectangle of the same size
Dim stringSize As SizeF = g.MeasureString("Hello", font)
Dim coorX As Single = 0
Dim coorY As Single = -stringSize.Height
For i As Integer = 0 To 255 Step 30
Using myBrush As SolidBrush = New SolidBrush(Color.FromArgb(255, CInt(i), CInt(255 - i), CInt(i))) 'Green to violet
g.TranslateTransform(200, 200)
g.RotateTransform(-i)
g.DrawString("Hello", font, myBrush, coorX, coorY)
g.DrawRectangle(New Pen(Color.FromArgb(50, 255, 0, 0), 1), coorX, coorY, stringSize.Width, stringSize.Height)
g.ResetTransform()
End Using
Next
End Using
'Draw the center of the rotation
g.DrawRectangle(Pens.Black, 200 - 5, 200 - 5, 10, 10)
End Using
End Sub

Custom CheckBox background issue

I was trying to build a custom CheckBox, but I see a black rectangle around it. Why does this happen? And why the second CheckBox has the first overlapped?
It looks like there's a black rectangle in a default position of the control. When I add one more CheckBox, the second looks like 2 CheckBox-es in the same position.
Public Class mycheckbox
Inherits CheckBox
Protected Overrides Sub onpaint(pevent As PaintEventArgs)
pevent.Graphics.FillRectangle(New SolidBrush(BackColor), Location.X, Location.Y, Width, Height)
Dim brsh As New SolidBrush(Color.YellowGreen)
Dim boxside As Integer = CInt(pevent.Graphics.MeasureString(Text, Font, Width).Height)
pevent.Graphics.FillRectangle(brsh, Location.X, Location.Y, Width, Height)
If Checked And Enabled Then
pevent.Graphics.DrawImage(My.Resources.X, Location.X + 1, Location.Y + 1, 18, 18)
pevent.Graphics.DrawRectangle(Pens.Black, New Rectangle(Location.X, Location.Y, 19, 19))
pevent.Graphics.DrawString(Text, Font, Brushes.Black, boxside + 15, 11)
End If
brsh.Dispose()
End Sub
End Class
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim mcb1 As New mycheckbox
Dim mcb2 As New mycheckbox
mcb1.Name = "cb1"
mcb1.Text = "Hello!!!"
mcb1.Location = New Point(10, 10)
mcb1.Size = New Size(300, 30)
mcb2.Name = "cb2"
mcb2.Text = "Hi!!!"
mcb2.Location = New Point(10, 50)
mcb2.Size = New Size(300, 30)
Me.Controls.Add(mcb1)
Me.Controls.Add(mcb2)
End Sub

Collision between ball and curve as graphics objects

I am trying to make a game where I bounce a ball off of the ground which is drawn as a closed curve (The green part), I just don't know how I would go about calculating the collision between the ball and curve.
I've drawn both the ball and curve using graphics in a picturebox, I imagine I have to do it mathematically as I can't find any builtin functionality in Visual basic that lets me do it.
My code:
Public Class Form1
Dim BallSpeedY, BallSpeedX As Double
Dim BallLoc As Point
Dim Start As Boolean = False
Dim gameTime As Decimal = 60.1
Dim gameTimeFont As New Font("Arial", 24, FontStyle.Bold)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
'Size of the picturebox that is being drawn on
PictureBox1.Width = Me.Width
PictureBox1.Height = Me.Height - 24
DrawGame(False, False, True)
End Sub
Private Sub DrawGame(refreshMap As Boolean, drawBall As Boolean, drawTime As Boolean)
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
Static startcornerpt As PointF
Static firstpt As PointF
Static pt2 As PointF
Static pt3 As PointF
Static pt4 As PointF
Static pt5 As PointF
Static lastpt As PointF
Static Endcornerpt As PointF
' Clears the window
g.Clear(Color.White)
If refreshMap Then
Randomize() ' The rnd seed would always be the same if this is not done
' Creates 5 points chosen at random positions on the window within certain parameters
startcornerpt = New PointF(0, Me.Height)
pt2 = New PointF(Me.Width * 0.2, Me.Height * ((39 * Rnd() + 30) / 100))
firstpt = New PointF(0, pt2.Y * 0.5 * 2)
pt3 = New PointF(Me.Width * 0.4, Me.Height * ((39 * Rnd() + 30) / 100))
pt4 = New PointF(Me.Width * 0.6, Me.Height * ((39 * Rnd() + 30) / 100))
pt5 = New PointF(Me.Width * 0.8, Me.Height * ((39 * Rnd() + 30) / 100))
lastpt = New PointF(Me.Width, pt5.Y * 0.5 * 2)
Endcornerpt = New PointF(Me.Width, Me.Height)
End If
' Draws the map with the 5 points
Dim curvepoints As PointF() = {startcornerpt, firstpt, pt2, pt3, pt4, pt5, lastpt, Endcornerpt}
g.FillClosedCurve(Brushes.PaleGreen, curvepoints)
If drawBall Then
' Draws the ball
g.DrawEllipse(Pens.Blue, BallLoc.X, BallLoc.Y, 20, 20)
g.FillEllipse(Brushes.Blue, BallLoc.X, BallLoc.Y, 20, 20)
' Accelerates speed
BallSpeedY = BallSpeedY - 1
' Update position
BallLoc = New Point(BallLoc.X + BallSpeedX, BallLoc.Y - BallSpeedY)
End If
If drawTime Then
gameTime = gameTime - 0.1
gameTime.ToString()
g.DrawString(gameTime, gameTimeFont, Brushes.Black, Me.Width / 2 - 120, Me.Height * 0.025) ' Draws the gametime on screen,
' Width is set to be around the middle of the screen while height is just under the strip menu.
End If
PictureBox1.Refresh()
End Sub
Private Sub StartToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles StartToolStripMenuItem.Click
If Start = False Then
gameTime = 60.1
'Resets ball for testing
BallLoc.X = 800
BallLoc.Y = 300
BallSpeedY = 0
'Starts the timers
Gravity.Start()
Movement.Start()
Start = True
ElseIf Start = True Then
' Resets the ball
Dim ballloc As New Point(800, 300)
Gravity.Stop()
Movement.Stop()
Start = False
End If
End Sub
Private Sub NewMapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewMapToolStripMenuItem.Click
' Creates a new map
DrawGame(True, False, False)
Start = False
End Sub
Private Sub Movement_Tick(sender As Object, e As EventArgs) Handles Movement.Tick
' Starts movement of the ball
DrawGame(False, True, True)
End Sub
End Class
EDIT: Collision now works with these additions:
Dim wider = CType(ground.Clone(), GraphicsPath)
Using widenizer As Pen = New Pen(Color.Black, ballDiameter)
wider.Widen(widenizer)
End Using
And:
If ground.IsVisible(BallLoc) OrElse wider.IsVisible(BallLoc) Then
BallSpeedY = BallSpeedY + 50 ' rebound on collision
End If
The code below illustrates the comment I've added about using Widen() so you can test using the center of the ball.
It has been ages since I've done any VB.NET, but it does show the idea:
Imports System.Drawing.Drawing2D
Partial Public Class Form1
Inherits Form
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
Dim diameter As Integer = 10
Dim path As GraphicsPath = New GraphicsPath()
path.AddCurve(New Point() {New Point(0, 100), New Point(200, 200), New Point(400, 100)})
path.AddLines(New Point() {New Point(400, 400), New Point(0, 400)})
path.CloseAllFigures()
e.Graphics.FillPath(Brushes.Green, path)
Dim wider = CType(path.Clone(), GraphicsPath)
Using widenizer As Pen = New Pen(Color.Black, diameter)
wider.Widen(widenizer)
End Using
For x As Integer = 0 To 400 Step diameter
For y As Integer = 0 To 400 Step diameter
If path.IsVisible(x, y) OrElse wider.IsVisible(x, y) Then
e.Graphics.DrawEllipse(Pens.Red, CType(x - diameter / 2, Single), CType(y - diameter / 2, Single), diameter, diameter)
Else
e.Graphics.DrawEllipse(Pens.Blue, CType(x - diameter / 2, Single), CType(y - diameter / 2, Single), diameter, diameter)
End If
Next y
Next x
End Sub
End Class
It fills the area with circles, where the red ones are "touching" the ground:

To make the custom trackbar smaller by changing more than 1 value in one scroll move

I have created a custom trackbar that gives values between 100-1600. The problem is that i havent been able to reduce the size of the trackbar. The trackbar has to have the width as 1600 for a user to be able to access all the values and keep the thumb in the trackbar at the same time. Here is my code :
Public Class myTrackBar
Inherits Control
'Public Value As Integer
Private Pointer As New Bitmap(25, 30)
Private Rect As New Rectangle(100, 0, 20, 30)
Public Event Scroll(ByVal Sender As Object, ByVal e As ValueChangedEventArgs)
Private Moving As Boolean
Private Offset As Integer
Public Sub New()
'Size = New Size(210, 50)
DoubleBuffered = True
Using g As Graphics = Graphics.FromImage(Pointer)
g.Clear(Color.White)
g.FillRectangle(Brushes.DarkBlue, New Rectangle(0, 0, 50, 50))
'g.FillPolygon(Brushes.Blue, New Point() {New Point(0, 15), New Point(5, 20), New Point(10, 15)})
'g.FillEllipse(Brushes.DarkBlue, 0, 0, 19, 19)
End Using
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.FillRectangle(Brushes.White, New Rectangle(0, 0, Width - 100, Height))
Dim X As Integer = 15
' For count As Integer = 1 To 10
e.Graphics.DrawLine(New Pen(Brushes.Green, 16), New Point(0, 15), New Point(Width - 100, 15))
' X += 20
'Next
' Using P As New Pen(Brushes.Black, 1)
'P.DashStyle = Drawing2D.DashStyle.Dot
'e.Graphics.DrawRectangle(P, New Rectangle(100, 1, Width - 5, Height - 5))
'End Using
e.Graphics.DrawImage(Pointer, Rect)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
If Rect.Contains(e.Location) Then
Moving = True
Offset = (e.Location.X - Rect.X)
End If
End Sub
Protected Overrides Sub OnMouseup(ByVal e As System.Windows.Forms.MouseEventArgs)
Moving = False
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
If Moving Then
Rect.X = Math.Min(Math.Max(e.Location.X - Offset, 0), 1500)
Invalidate()
RaiseEvent Scroll(Me, New ValueChangedEventArgs(Rect.X))
End If
End Sub
Public Property Value As Integer
Get
Return CInt((Rect.X + 100))
End Get
Set(ByVal value As Integer)
Rect.X = CInt(value)
End Set
End Property
End Class
There are various dlls available online for trackbars. If you want to simply use it in a project you can simply import the dll files into the project and use them like any other element.

Creating multiple, independent, threads on a form

I am trying to emulate a 'horse race' with VB Express 2013 which has exposed a gap in my understanding of how threads work with windows forms. The idea is that a blue square and a red square (the horses) race from left to right across a form (which has a white background) when a button on the form is pressed. Each increment of movement should be (pseudo) randomly generated, so the winner should be unpredictable.
Here is the code I have used. The movement of the squares is indeed random, but they move together, not independently, so the race is always a tie. If I include Randomize in only one of the thread procedures, it behaves more like a race but the winner is usually predictable. Could someone please tell me what I am missing? Thanks in anticipation.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim t1 As System.Threading.Thread
Dim t2 As System.Threading.Thread
t1 = New System.Threading.Thread(AddressOf RedHorse)
t2 = New System.Threading.Thread(AddressOf BlueHorse)
t1.Start()
t2.Start()
End Sub
Public Sub RedHorse()
Randomize()
Dim G As Graphics
G = Me.CreateGraphics
Dim bRed As Brush
bRed = New SolidBrush(Color.Red)
Dim bWhite As Brush
bWhite = New SolidBrush(Color.White)
Dim x1 As Integer
x1 = 100
G.FillRectangle(bWhite, x1, 100, 50, 50)
Do Until x1 >= 800
x1 = x1 + Rnd()
G.FillRectangle(bRed, x1, 100, 50, 50)
Threading.Thread.Sleep(1)
G.FillRectangle(bWhite, x1, 100, 50, 50)
Loop
End Sub
Public Sub BlueHorse()
Randomize()
Dim G As Graphics
G = Me.CreateGraphics
Dim bBlue As Brush
bBlue = New SolidBrush(Color.Blue)
Dim bWhite As Brush
bWhite = New SolidBrush(Color.White)
Dim x2 As Integer
x2 = 100
G.FillRectangle(bWhite, x2, 200, 50, 50)
Do Until x2 >= 800
x2 = x2 + Rnd()
G.FillRectangle(bBlue, x2, 200, 50, 50)
Threading.Thread.Sleep(1)
G.FillRectangle(bWhite, x2, 200, 50, 50)
Loop
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Dim G As Graphics
G = Me.CreateGraphics
Dim bRed As Brush
bRed = New SolidBrush(Color.Red)
Dim bBlue As Brush
bBlue = New SolidBrush(Color.Blue)
G.FillRectangle(bRed, 100, 100, 50, 50)
G.FillRectangle(bBlue, 100, 200, 50, 50)
End Sub
End Class
First of all don't use Randomize, use the Random class, read up on this. The basic problem was that the threads started at the same time and then slept for the same time between loops. Here is your code with a few changes.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Me.Width = 1000 'testing
isWinner = -1
Dim t1 As System.Threading.Thread
Dim t2 As System.Threading.Thread
t1 = New System.Threading.Thread(AddressOf RedHorse)
t2 = New System.Threading.Thread(AddressOf BlueHorse)
t1.Start()
t2.Start()
End Sub
Dim prng As New Random
Const maxMove As Integer = 21
Const maxSleep As Integer = 51
Dim isWinner As Integer = -1
Public Sub RedHorse()
Threading.Thread.Sleep(prng.Next(maxSleep))
Dim G As Graphics
G = Me.CreateGraphics
Dim bRed As Brush
bRed = New SolidBrush(Color.Red)
Dim bWhite As Brush
bWhite = New SolidBrush(Color.White)
Dim x1 As Integer
x1 = 100
G.FillRectangle(bWhite, x1, 100, 50, 50)
Do While x1 < 800 AndAlso isWinner < 0
x1 = x1 + prng.Next(maxMove)
G.FillRectangle(bRed, x1, 100, 50, 50)
Threading.Thread.Sleep(prng.Next(maxSleep))
G.FillRectangle(bWhite, x1, 100, 50, 50)
Loop
'G.FillRectangle(bRed, x1, 100, 50, 50)
If isWinner < 0 Then
isWinner = 1
End If
End Sub
Public Sub BlueHorse()
Threading.Thread.Sleep(prng.Next(maxSleep))
Dim G As Graphics
G = Me.CreateGraphics
Dim bBlue As Brush
bBlue = New SolidBrush(Color.Blue)
Dim bWhite As Brush
bWhite = New SolidBrush(Color.White)
Dim x2 As Integer
x2 = 100
G.FillRectangle(bWhite, x2, 200, 50, 50)
Do While x2 < 800 AndAlso isWinner < 0
x2 = x2 + prng.Next(maxMove)
G.FillRectangle(bBlue, x2, 200, 50, 50)
Threading.Thread.Sleep(prng.Next(maxSleep))
G.FillRectangle(bWhite, x2, 200, 50, 50)
Loop
'G.FillRectangle(bBlue, x2, 200, 50, 50)
If isWinner < 0 Then
isWinner = 2
End If
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Dim G As Graphics
G = Me.CreateGraphics
Dim bRed As Brush
bRed = New SolidBrush(Color.Red)
Dim bBlue As Brush
bBlue = New SolidBrush(Color.Blue)
G.FillRectangle(bRed, 100, 100, 50, 50)
G.FillRectangle(bBlue, 100, 200, 50, 50)
End Sub
End Class