how can I create smooth corner rounded form in vb .net
I have no idea how I can do this.
In the image above, this has been done, but as you can see, it is pixelated.
Try this , smoother corners
Private borderForm As New Form
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
With Me
.FormBorderStyle = Windows.Forms.FormBorderStyle.None
.Region = New Region(RoundedRectangle(.ClientRectangle, 50))
End With
With borderForm
.ShowInTaskbar = False
.FormBorderStyle = Windows.Forms.FormBorderStyle.None
.StartPosition = FormStartPosition.Manual
.BackColor = Color.Black
.Opacity = 0.25
Dim r As Rectangle = Me.Bounds
r.Inflate(2, 2)
.Bounds = r
.Region = New Region(RoundedRectangle(.ClientRectangle, 50))
r = New Rectangle(3, 3, Me.Width - 4, Me.Height - 4)
.Region.Exclude(RoundedRectangle(r, 48))
.Show(Me)
End With
End Sub
Private Function RoundedRectangle(rect As RectangleF, diam As Single) As Drawing2D.GraphicsPath
Dim path As New Drawing2D.GraphicsPath
path.AddArc(rect.Left, rect.Top, diam, diam, 180, 90)
path.AddArc(rect.Right - diam, rect.Top, diam, diam, 270, 90)
path.AddArc(rect.Right - diam, rect.Bottom - diam, diam, diam, 0, 90)
path.AddArc(rect.Left, rect.Bottom - diam, diam, diam, 90, 90)
path.CloseFigure()
Return path
End Function
Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
Dim r As New Rectangle(1, 1, Me.Width - 2, Me.Height - 2)
Dim path As Drawing2D.GraphicsPath = RoundedRectangle(r, 48)
Using pn As New Pen(Color.Black, 2)
e.Graphics.DrawPath(pn, path)
End Using
End Sub
Related
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:
How do I erase a graphic as it is moving along the screen? As my code is now it draws the shape on screen multiple times and doesn't ever erase them so it ends up looking like the attached picture.
picture
I'm trying to make a game where you shoot a ball from a cannon but I'm having trouble getting the ball to move smoothly and without the ball being on screen multiple places at the same time.
All of the code used:
Public Class Form1
Dim BMP As New Bitmap(6000, 6000)
Dim ball As Graphics = Graphics.FromImage(BMP)
Dim Map As Graphics = Graphics.FromImage(BMP)
Dim BallSpeedY, BallSpeedX As Integer
Dim BallLoc As Point
Dim Start As Boolean = False
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
End Sub
Private Sub StartToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles StartToolStripMenuItem.Click
If Start = False Then
'Resets ball for testing
BallLoc.X = 800
BallLoc.Y = 300
BallSpeedY = 0
'Starts the timers
Gametime.Start()
Gravity.Start()
MovementY.Start()
MovementX.Start()
Start = True
ElseIf Start = True Then
Dim ballloc As New Point(800, 300)
Start = False
End If
End Sub
Private Sub NewMapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewMapToolStripMenuItem.Click
Map.Clear(Color.White)
Randomize()
' Draws map
Dim firstpt As New Point(0, Me.Height * 0.7)
Dim pt2 As New Point(Me.Width * 0.2, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
Dim pt3 As New Point(Me.Width * 0.4, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
Dim pt4 As New Point(Me.Width * 0.6, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
Dim pt5 As New Point(Me.Width * 0.8, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
Dim lastpt As New Point(Me.Width, Me.Height * 0.7)
Dim curvepoints As Point() = {firstpt, pt2, pt3, pt4, pt5, lastpt}
Map.DrawCurve(Pens.Red, curvepoints)
PictureBox1.Image = BMP
End Sub
Private Sub Gametime_Tick(sender As Object, e As EventArgs) Handles Gametime.Tick
End Sub
Private Sub MovementY_Tick(sender As Object, e As EventArgs) Handles MovementY.Tick
' Draws the ball
ball.DrawEllipse(Pens.Blue, BallLoc.X, BallLoc.Y, 20, 20)
ball.FillEllipse(Brushes.Blue, BallLoc.X, BallLoc.Y, 20, 20)
' Accelerated speed
BallSpeedY = BallSpeedY - 1
' Updates position
BallLoc = New Point(BallLoc.X + BallSpeedX, BallLoc.Y - BallSpeedY)
' Redraws image
PictureBox1.Image = BMP
End Sub
End Class
You're drawing on a bitmap and setting that to your PictureBox image. Try this...
In your tick event, draw everything directly on the PictureBox Graphics object and refresh the PictureBox. The points are saved as Static variables so as the ball is moving, the same map is generated behind it and whenever you choose new map, it will generate new points and redraw the map.
Basically the concept is to calculate different object movements and then draw everything in one place making sure to draw it in layers: background, next foreground object, etc.
Private Sub NewMapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewMapToolStripMenuItem.Click
DrawGame(True, True)
'Or if you just want a new map and not the ball use: DrawGame(True, False)
End Sub
Private Sub MovementY_Tick(sender As Object, e As EventArgs) Handles MovementY.Tick
DrawGame(False, True)
End Sub
Private Sub DrawGame(refreshMap As Boolean, drawBall As Boolean)
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)
Static firstpt As Point
Static pt2 As Point
Static pt3 As Point
Static pt4 As Point
Static pt5 As Point
Static lastpt As Point
g.Clear(Color.White)
If refreshMap Then
Randomize()
' Generate new points
firstpt = New Point(0, Me.Height * 0.7)
pt2 = New Point(Me.Width * 0.2, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
pt3 = New Point(Me.Width * 0.4, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
pt4 = New Point(Me.Width * 0.6, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
pt5 = New Point(Me.Width * 0.8, Me.Height * (((70 - 30 + 1) * Rnd() + 30) / 100))
lastpt = New Point(Me.Width, Me.Height * 0.7)
End If
Dim curvepoints As Point() = {firstpt, pt2, pt3, pt4, pt5, lastpt}
g.DrawCurve(Pens.Red, 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)
' Accelerated speed
BallSpeedY = BallSpeedY - 1
' Updates position
BallLoc = New Point(BallLoc.X + BallSpeedX, BallLoc.Y - BallSpeedY)
End If
PictureBox1.Refresh()
End Sub
And then you don't need this:
Dim BMP As New Bitmap(6000, 6000)
Dim ball As Graphics = Graphics.FromImage(BMP)
Dim Map As Graphics = Graphics.FromImage(BMP)
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
I want to place my Crop Control on center of image of picture box. I have tried following code
Dim oCropControl As new CropControl
Dim oControlLocation As Point
oControlLocation = New Point(peImageViewer.Width / 2, peImageViewer.Height / 2)
oCropControl.Location = New Point(oControlLocation.X, oControlLocation.Y)
But this is not working well.. :( Crop Control shown in bottom.
Thanks in advance!!
Assuming they are both parented to the same control you could do it like this:
Dim rect1 As Rectangle = Me.myPictureBox.Bounds
Dim rect2 As Rectangle = Me.myCropControl.Bounds
rect2.X = CInt(rect1.X + ((rect1.Width / 2) - (rect2.Width / 2)))
rect2.Y = CInt(rect1.Y + ((rect1.Height / 2) - (rect2.Height / 2)))
Me.myCropControl.Bounds = rect2
Me.myCropControl.BringToFront()
Example
Public Class Form1
Public Sub New()
Me.InitializeComponent()
Me.Size = New Size(400, 400)
Me.StartPosition = FormStartPosition.CenterScreen
Me.myButton = New Button() With {.Location = New Point(3, 3), .Text = "ALIGN!"}
Me.myCropControl = New Label() With {.Bounds = New Rectangle(245, 263, 60, 60), .BackColor = Color.Blue, .ForeColor = Color.White, .Text = "CROP", .TextAlign = ContentAlignment.MiddleCenter}
Me.myPictureBox = New PictureBox() With {.Bounds = New Rectangle(23, 56, 246, 143), .BackColor = Color.Red}
Me.Controls.AddRange({Me.myButton, Me.myCropControl, Me.myPictureBox})
End Sub
Private Sub Align(sender As Object, e As EventArgs) Handles myButton.Click
Dim rect1 As Rectangle = Me.myPictureBox.Bounds
Dim rect2 As Rectangle = Me.myCropControl.Bounds
rect2.X = CInt(rect1.X + ((rect1.Width / 2) - (rect2.Width / 2)))
rect2.Y = CInt(rect1.Y + ((rect1.Height / 2) - (rect2.Height / 2)))
Me.myCropControl.Bounds = rect2
Me.myCropControl.BringToFront()
End Sub
Private WithEvents myButton As Button
Private myCropControl As Label
Private myPictureBox As PictureBox
End Class
I have this code that I wrote up, but this code was used when I left clicked on the form, but wasn't a random number of circles. I am wondering how I can adapt it to draw 5-10 random circles with random colors across the form when I click a button, but it has to use a loop. Thanks!!
Private Sub CirclePainterForm_MouseDown(ByVal sender As _
Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles MyBase.MouseDown
Dim graphicsObject As Graphics = CreateGraphics()
Dim randomObject As Random = New Random
Dim diameter As Integer = randomObject.Next(5, 200)
If e.Button = Windows.Forms.MouseButtons.Left Then
graphicsObject.FillEllipse(New SolidBrush(RandomColor()), e.X, e.Y, _
diameter, diameter)
graphicsObject.FillEllipse(New SolidBrush(RandomColor()), e.X + 250, e.Y, _
diameter + 50, diameter + 50)
graphicsObject.FillEllipse(New SolidBrush(RandomColor()), e.X + 500, e.Y, _
diameter + 75, diameter + 75)
graphicsObject.FillEllipse(New SolidBrush(RandomColor()), e.X + 750, e.Y, _
diameter + 100, diameter + 100)
graphicsObject.FillEllipse(New SolidBrush(RandomColor()), e.X + 1000, e.Y, _
diameter + 125, diameter + 125)
Add a button to your form and add code for the Click event:
To do Circles Or Squares [and updated with your/my comments]
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim rnd As New Random(), rndCol As New Random(DateTime.Now.Ticks Mod ((rnd.Next) + 1))
Dim numShapes = rnd.Next(5, 11), bIsCircleOrSquare As Boolean = (rnd.Next Mod 2)
Using g = Me.CreateGraphics()
g.Clear(Me.BackColor)
Dim diam = rnd.Next(55, Math.Min(255, ClientSize.Width))
While numShapes > 0
Using b As New SolidBrush(Color.FromArgb(rndCol.Next(100, 256), rndCol.Next(256), rndCol.Next(256), rndCol.Next(256)))
Dim x = rnd.Next(ClientSize.Width - diam), y = rnd.Next(ClientSize.Height - diam)
If bIsCircleOrSquare Then
g.FillRectangle(b, x, y, diam, diam)
g.DrawRectangle(Pens.Black, x, y, diam, diam)
Else
g.FillEllipse(b, x, y, diam, diam)
g.DrawEllipse(Pens.Black, x, y, diam, diam)
End If
End Using
numShapes -= 1
End While
End Using
End Sub
If you want to see the circles overlap you can replace:
Using b As New SolidBrush(Color.FromArgb(rndCol.Next(100,256), rndCol.Next(256), rndCol.Next(256), rndCol.Next(256)))
with
Using b As New SolidBrush(Color.FromArgb(255, rndCol.Next(256), rndCol.Next(256), rndCol.Next(256)))