Drawing reflection of a progressbar control in winforms VB - vb.net

Here is an image of what I am trying to achieve:
As you can see, there is a slight reflection under the progress bar.
I have a custom progress bar that is heavily based on this code:
http://www.codeproject.com/Articles/19309/Vista-Style-Progress-Bar-in-C
Note: My code is in VB.
Problem - I would like to draw a reflection of that progress bar under it so it looks similar to the image I have given above. I have been told that one way to do it is using pixels, which need to be done manually. Is that the only option? Is there any other/easier way to do it?
I appreciate your help.
Thanks!

Are you looking for something like this?
Here is the code:
Dim pgBarReflection As New Bitmap(ProgressBar1.Width, 20)
ProgressBar1.DrawToBitmap(pgBarReflection, ProgressBar1.ClientRectangle)
For x As Integer = 0 To pgBarReflection.Width - 1
For y As Integer = 0 To pgBarReflection.Height - 1
Dim alpha = 255 - 255 * y \ pgBarReflection.Height
Dim clr As Color = pgBarReflection.GetPixel(x, y)
clr = Color.FromArgb(alpha, clr.R, clr.G, clr.B)
pgBarReflection.SetPixel(x, y, clr)
Next y
Next x
Me.CreateGraphics.DrawImage(pgBarReflection, New Point(ProgressBar1.Left, ProgressBar1.Bottom + 10))
If you want greyscale shadow, replace this line
clr = Color.FromArgb(alpha, clr.R, clr.G, clr.B)
with these two:
Dim greyScale As Integer = CInt(clr.R * 0.3 + clr.G * 0.59 + clr.B * 0.11)
clr = Color.FromArgb(alpha, greyScale, greyScale, greyScale)
You will get something like this:
You can play with parameters to make the shadow more realistic.
Solution is based on this article:
Draw an image with gradient alpha (opacity) values in VB.NET

This solution serves more code but is many times faster than GetPixel/SetPixel. It has one overload without any further settings, or you can use it with alpha start and stop value as well as how much you want to "squeeze" the reflection.
The overloaded simple version assume the background color to be that of the parent. Please note that it has no error checking. You will of course need to implement this in production code.
The result will be like this: (a big thanks to Neolisk for going through the extra trouble producing an image from the code)
The is still room for optimizations (working with "squeezed" version only, un-boxing calculations etc.), but I'll leave that as an execise for the user :-)
Private Sub DrawControlReflection(c As Control)
DrawControlReflection(c, c.Parent.BackColor, 1, 0, 1, 7) 'set you defaults here
End Sub
''' <summary>
''' Draws an reflection of a control
''' </summary>
''' <param name="c">The control to make an reflection of</param>
''' <param name="bgCol">Background color in transparent area</param>
''' <param name="startTrans">0.0-1.0, start value of reflection transparency, usually 1</param>
''' <param name="endTrans">0.0-1.0, end value of reflection transparency, usually 0</param>
''' <param name="squeeze">height of reflection, values 0-1, 1=100%, 0.5=50% etc.</param>
''' <param name="delta">y offset of reflection from control's bottom</param>
''' <remarks>
''' Provided AS-IS.
''' Created by Epistmex, use as you want.
''' Need implementation of error checking (bitmap allocations etc.)
''' </remarks>
Private Sub DrawControlReflection(c As Control,
bgCol As Color,
startTrans As Single,
endTrans As Single,
squeeze As Single,
delta As Integer)
'
'-- Original control's bound
'
Dim r As Rectangle = c.ClientRectangle
'
'-- Destination bound
'
Dim rd As Rectangle = New Rectangle(c.Left,
c.Top + r.Height + 1 + delta,
r.Width,
CInt(r.Height * squeeze))
'
'-- Create a bitmap for reflection and copy control content into it
'
Dim bmp As New Bitmap(r.Width,
r.Height,
Imaging.PixelFormat.Format24bppRgb)
c.DrawToBitmap(bmp, r)
'
'-- flip it vertically
'
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY)
'
'-- Add gradient "transparency" to bitmap
'
AddGradientAlpha(bmp, r, startTrans, endTrans, bgCol)
'
'-- Draw the result
'
Dim g As Graphics = c.Parent.CreateGraphics
if squeeze <> 1 Then g.InterpolationMode = _
Drawing2D.InterpolationMode.HighQualityBicubic
g.DrawImage(bmp, rd)
g.Dispose()
bmp.Dispose()
End Sub
Private Sub AddGradientAlpha(ByRef bmp As Bitmap, r As Rectangle, s As Single, e As Single, bc As Color)
Dim bmpLock As Imaging.BitmapData = bmp.LockBits(r, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format24bppRgb)
Dim st As Integer = bmpLock.Stride
Dim bytesBmp(bmpLock.Stride * bmp.Height) As Byte
Runtime.InteropServices.Marshal.Copy(bmpLock.Scan0, bytesBmp, 0, bytesBmp.Length)
'
'-- Calculate and create pre-multiplied gradient alpha
'
Dim x, y, dx, l, d As Integer
Dim aDiff As Double = s - e
Dim a As Double
Dim b As Byte
Dim h As Integer = bmp.Height - 1
For y = 0 To h
l = y * st 'line. cache the calculations we can
d = h - y 'position with opposite value
If d = 0 Then
a = e
Else
a = (aDiff * d / h) + e 'gradient value ad 0.5 to h for even more accuracy
End If
If a < 0 Then a = 0
If a > 1 Then a = 1
a = a * a 'power of 2 to make gradient steeper
For x = 0 To bmp.Width - 1
dx = l + x * 3 'x pos in buffer
'make gradient of colors in buffer + mix bg color
bytesBmp(dx) = CByte(bytesBmp(dx) * a + ((1 - a) * bc.B))
bytesBmp(dx + 1) = CByte(bytesBmp(dx + 1) * a + ((1 - a) * bc.G))
bytesBmp(dx + 2) = CByte(bytesBmp(dx + 2) * a + ((1 - a) * bc.R))
Next
Next
'
'-- Marshal back
'
Runtime.InteropServices.Marshal.Copy(bytesBmp, 0, bmpLock.Scan0, bytesBmp.Length)
bmp.UnlockBits(bmpLock)
End Sub

Related

Creating a repeating line through looping by giving the x and y coordinates

I am experimenting on the paint event of VB.Net, and for this experiment I would like to create a repeating horizontal or vertical (depending on the parameter that I inputted) line and loop through until it meets the corresponding end point x and y.
Something like this:
What I'm trying to achieve is given the x and y start point and x and y end point the function should create either vertical or horizontal line that starts with the given start point until it reaches the given end point.
I can create curveline and straightline using the paintevent, but right now I don't have any idea on how to perform looping in the given x and y start point and end point.
You just need to use a For loop to iterate the x/y coordinates. Here's an example:
Public Class Form1
Private Enum Orientation
Vertical
Horizontal
End Enum
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim orient As Orientation = Orientation.Vertical
Dim x As Integer = 100 'X Coord
Dim y As Integer = 100 'Y Coord
Dim count As Integer = 10 'Number of Lines to draw
Dim spacing As Integer = 5 'Spacing between lines in pixels
Dim length As Integer = 20 'Length of each line in pixels
Dim thickness As Integer = 3 'Thickness of each line in pixels
drawLines(x, y, orient, count, spacing, length, thickness, e.Graphics)
End Sub
Private Sub drawLines(x As Integer, y As Integer, orient As Orientation, count As Integer, spacing As Integer, length As Integer, thickness As Integer, g As Graphics)
'Create the Pen in a using block so it will be disposed.
'The code uses a red pen, you can use whatever color you want
Using p As New Pen(Brushes.Red, CSng(thickness))
'Here we iterate either the x or y coordinate to draw each
'small segment.
For i As Integer = 0 To count - 1
If orient = Orientation.Horizontal Then
g.DrawLine(p, x + ((thickness + spacing) * i), y, x + ((thickness + spacing) * i), y + length)
Else
g.DrawLine(p, x, y + ((thickness + spacing) * i), x + length, y + ((thickness + spacing) * i))
End If
Next
End Using
End Sub
End Class
Have you tried something like:
For x = xstart to xend Step Spacing
Next
Where:
xstart = your start point
xend = your end point
Spacing = distance between lines

Creating a Custom Polygon Class in vb.net

I want to make a custom polygon shape class, which i can drag and drop unto my form at will (just as it is done in the case of OvalShape and RectangleShape objects in VS toolbox). I checked site1, site2 and site3, one of which specifically said that the OnPaint Event of my form should be overridden. Is there any way I can achieve the same while creating the custom polygon shape, and still have my polygon appear on the toolbox?
Edit:
#Jens: I'll like the control to generate its code with the following tested code:
Me.ClientSize = New Point(24, 24)
Dim r1 As Integer = Min(cx, cy) - 10
Dim r2 As Integer = Min(cx, cy) \ 2
Dim pts(9) As Point
For i As Integer = 0 To 9 Step 2
pts(i).X = cx + CInt(r1 * Cos(i * PI / 5 - PI / 2))
pts(i).Y = cy + CInt(r1 * Sin(i * PI / 5 - PI / 2))
pts(i + 1).X = cx + CInt(r2 * Cos((i + 1) * PI / 5 - PI / 2))
pts(i + 1).Y = cy + CInt(r2 * Sin((i + 1) * PI / 5 - PI / 2))
Next i
That gives me a star with 5 spikes. How can i store them in the Points variable created,
OR
store the points as a region so that whenever i change forecolor, it fills the region (i.e. polygn) with the selected color. I also want to prevent painting the backcolor. Please take a look at the links below to a c# solution of what i really want, but i suck at converting c# to vb.
link1; Link2
Thanks a lot
I am not entirely sure that that is what you want. You can always derive a new class from Control and use its Paint event to draw whatever you like. In your case a polygon.
The control therefore contains a Points property that is just an array of PointF values that define the edges of the polygon. By using the DesignerSerializationVisible.Content attribute you make it possible to edit these values through the designer directly. The code looks like this:
Public Class PolygonControl
Inherits Control
Private _Points(2) As PointF
<System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)>
Public Property Points As PointF()
Get
Return _Points
End Get
Set(value As PointF())
_Points = value
End Set
End Property
Public Property LineColor As Color = Color.Black
Public Property LineWidth As Integer = 2
Private Sub PolygonControl_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
e.Graphics.Clear(Me.BackColor)
If Points IsNot Nothing AndAlso Points.Count > 1 Then
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Using b As New SolidBrush(ForeColor)
Using p As New Pen(b, LineWidth)
e.Graphics.DrawPolygon(p, Points)
End Using
End Using
End If
End Sub
End Class
I added a color and width property as well. This is just to give you a rough idea. Notice the attribute above the Points property.
In "action" it looks like this:
Adding better designer support is certainly possible, but I have no experience with that whatsoever. But it is a start.
Edit
Since you always draw the same shape, you can precalculate the points in the control's constructor and just draw the shape in the paint event:
Public Class StarControl
Inherits Control
'Storage for the shape's points
Private pts(9) As Point
'Constructor
Public Sub New()
Me.ClientSize = New Size(24, 24)
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Me.BackColor = Color.Transparent
'Precalculate the shape
Dim cx = CInt(Me.ClientSize.Width / 2)
Dim cy = CInt(Me.ClientSize.Height / 2)
Dim r1 As Integer = Min(cx, cy) - 10
Dim r2 As Integer = Min(cx, cy) \ 2
ReDim pts(9)
For i As Integer = 0 To 9 Step 2
pts(i).X = cx + CInt(r1 * Cos(i * PI / 5 - PI / 2))
pts(i).Y = cy + CInt(r1 * Sin(i * PI / 5 - PI / 2))
pts(i + 1).X = cx + CInt(r2 * Cos((i + 1) * PI / 5 - PI / 2))
pts(i + 1).Y = cy + CInt(r2 * Sin((i + 1) * PI / 5 - PI / 2))
Next i
End Sub
Public Property LineColor As Color = Color.Black
Public Property FillColor As Color = Color.Gold
Public Property LineWidth As Integer = 1
Public Sub PaintMe(sender As Object, e As PaintEventArgs) Handles Me.Paint
'Draw the precalculated shape
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Using b As New SolidBrush(FillColor)
e.Graphics.FillPolygon(b, pts)
End Using
Using b As New SolidBrush(LineColor)
Using p As New Pen(b, LineWidth)
e.Graphics.DrawPolygon(p, pts)
End Using
End Using
End Sub
End Class
For an even cooler effect move the shape calculation into the Paint event handler so the shape resizes itself based on the control's size. This allows you to draw stars of arbitrary size.

Optimal sizes to display X picture boxes in an given space

I searched before posting but couldn't find anything close to my issue.
What I need to figure out is how to come with the optimal width and height of picture boxes (with a 4:3 ratio), given the required number of boxes to be displayed, and the available space.
Now, it's not as simple as a just dividing the available space by the number of required boxes, because the available space is not a uniform shape, but rather two rectangles of which size may vary (see this picture, it's the a+b space).
If fact, I have tried starting from there with the following code :
Private Sub LayoutSnapshots()
Dim lTotalSpace As Single, lSnapsize As Single, sXSize As Single, sYSize As Single
Dim I As Integer, J As Integer, X As Integer = 0, Y As Integer = 0, oPic As PictureBox
' bSnaps is the number of picture boxes to be displayed
If stSetting.bSnaps = 0 Then Exit Sub
' oSnaps is a List(Of PictureBoxe) to groupp the actual picture boxes
If oSnaps.Count > 0 Then
For Each oCtrl As PictureBox In oSnaps
Me.Controls.Remove(oCtrl)
Next
End If
oSnaps.Clear()
' Calculating the a+b space shown on the picture
lTotalSpace = ((Me.ClientSize.Height - MenuStrip1.Height) * Me.ClientSize.Width) - ((picPreview.Width + iMargin) * (picPreview.Height + iMargin))
If lTotalSpace < 1 Then
MsgBox("Window is too small. Please adjust one of these settings : Window size, Snapshots count, Live free view size.", MsgBoxStyle.ApplicationModal Or MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly)
Exit Sub
End If
'calculating a single picture's size by dividing total space by the number of snaps
lSnapsize = Math.Truncate(lTotalSpace / stSetting.bSnaps)
'Calculating Height and Width, with 4:3 ratio
sXSize = Math.Truncate(Math.Sqrt((4 * lSnapsize) / 3))
sYSize = Math.Truncate(Math.Sqrt((3 * lSnapsize) / 4))
For I = 1 To stSetting.bSnaps
If oPic IsNot Nothing Then oPic = Nothing
oPic = New PictureBox
oPic.BackColor = Color.White
oPic.BorderStyle = BorderStyle.FixedSingle
oPic.Size = New Size(sXSize - 1, sYSize - 1)
oPic.Location = New Point(X * sXSize, (Y * sYSize) + MenuStrip1.Height)
oSnaps.Add(oPic)
' Layed them successively on screen, need to optimize this
If ((X + 2) * sXSize) > (Me.ClientSize.Width) Then
X = 0
Y += 1
Else
X += 1
End If
Next
For Each oCtrl As PictureBox In oSnaps
Me.Controls.Add(oCtrl)
Next
End Sub
But obviously with all the possibilities of windows resizing, I couldn't think of any practical way to optimize it.
I am pretty sure this has to do with "operation research", as I recall we did optimization problems like this back then when I was a student, but I'm not sure how to actually model this or even if it is solvable by linear programming.
I have figured this out. The solution is kind of a "brute force" technique, it doesn't always return the optimum BUT the error is merely a few pixels. I used the code below, it works but it might need further optimization in terms of spacing. I couldn't comment on everything since I have a time pressure right now, but still wanted to share the answer, so just take some time to analyze it :
Private Sub LayoutSnapshots()
Dim sA As Single, sB As Single, sTotal As Single, sSnap As Single, sWidth As Single, sHeight As Single
Dim iCount As Integer = stSetting.bSnaps, iFit As Integer, iX As Integer, iY As Integer, iYg As Integer, I As Integer
Dim rA As Rectangle, rB As Rectangle, oPic As PictureBox, lpLoc As New List(Of Point), pLoc As New Point
Static bWarn As Boolean
Dim gPic As Graphics
' bSnaps is the number of picture boxes to be displayed
If stSetting.bSnaps = 0 Then Exit Sub
' If controls already on form, remove them and start form scratch
If oSnaps.Count > 0 Then
For Each oCtrl As PictureBox In oSnaps
Me.Controls.Remove(oCtrl)
Next
End If
' oSnaps is a List(Of PictureBox) grooping the picture boxes. Clear it for now
oSnaps.Clear()
'sA, sB are the sizes of spaces A and B respectively
sA = (Me.ClientSize.Width * (Me.ClientSize.Height - (MenuStrip1.Height + picPreview.Height + iMargin)))
sB = ((Me.ClientSize.Width - (picPreview.Width + iMargin)) * (picPreview.Height + iMargin))
' Total free space
sTotal = sA + sB
' This condition is important. It ensures there is at least one solution
' before entering the loops bellow. Otherwise we might get stuck in an infinite loop
If (sTotal < (stSetting.bSnaps * stSetting.bSnaps)) Then
' bWarn is a static boolean. Since this Sub is called from Form_Resize event, we
' want to warn the user only once when there is no space.
' Otherwise it becomes annoying.
If bWarn Then MsgBox("Window is too small. Please adjust one of these settings : Window size, Snapshots count, Live free view size.", MsgBoxStyle.ApplicationModal Or MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly)
bWarn = False
Exit Sub
End If
bWarn = True
Me.UseWaitCursor = True
Do
'rA, rB are the bounding rectangles of spaces A and B respectively
rA = New Rectangle(0, MenuStrip1.Height, Me.ClientSize.Width, Me.ClientSize.Height - (MenuStrip1.Height + picPreview.Height + iMargin))
rB = New Rectangle(0, picPreview.Top, Me.ClientSize.Width - (picPreview.Width + iMargin), picPreview.Height + iMargin)
' A single box's size
sSnap = Math.Truncate(sTotal / iCount)
' Width and Height with 4:3 aspect ratio.
sWidth = Math.Truncate(Math.Sqrt((4 * sSnap) / 3))
sHeight = Math.Truncate(Math.Sqrt((3 * sSnap) / 4))
' iFit keeps track of how many boxes we could fit in total
iFit = 0
iYg = 0
lpLoc.Clear()
' It would be a bit too long to explain the next block of code and I have a deadline to meet
' I'll comenting on that later
iX = 0
iY = 0
Do While (rA.Height >= ((sHeight * (iY + 1)) + 1))
If (((iX + 1) * sWidth) + 1) <= rA.Width Then
iFit += 1
lpLoc.Add(New Point(rA.X + ((iX * sWidth) + 1), rA.Y + ((iYg * sHeight) + 1)))
iX += 1
Else
iX = 0
iY += 1
iYg += 1
End If
Loop
'Add unused space from A to B.
rB.Height = rB.Height + (rA.Height - ((iYg * sHeight) + 1))
iX = 0
iY = 0
Do While (rB.Height >= ((sHeight * (iY + 1)) + 1))
If (((iX + 1) * sWidth) + 1) <= rB.Width Then
iFit += 1
lpLoc.Add(New Point(rB.X + ((iX * sWidth) + 1), rA.Y + ((iYg * sHeight) + 1)))
iX += 1
Else
iX = 0
iY += 1
iYg += 1
End If
Loop
Application.DoEvents()
iCount += 1
Loop While iFit < stSetting.bSnaps
' Add controls to form. Lay them one next to each other.
iX = 0
iY = 0
For I = 1 To stSetting.bSnaps
If oPic IsNot Nothing Then oPic = Nothing
oPic = New PictureBox
oPic.BackColor = Color.Cyan
oPic.BorderStyle = BorderStyle.FixedSingle
oPic.Size = New Size(sWidth - 1, sHeight - 1)
oPic.Location = lpLoc(I - 1)
' Just for debugging, displays index of each box inside it.
oPic.Image = New Bitmap(oPic.Width, oPic.Height)
gPic = Graphics.FromImage(oPic.Image)
gPic.DrawString(I, New Font("Arial", 10, FontStyle.Regular), Brushes.Red, New Point(0, 0))
oSnaps.Add(oPic)
Me.Controls.Add(oSnaps.Last)
Next
'Catch Ex As Exception
'Finally
Me.UseWaitCursor = False
'End Try
End Sub
P.S : Anyone please feel free to add more explanation to the code if you want.

vb.net Image Manipulation

I was tasked today after creating a program to Add watermarks to also create one to remove that same watermark.
My thoughts are that it is now part of the image and can't be removed so easily.
Is this accurate or is the actually a way? ( that doesnt take 10 years)
thanks for any hints
Here is my code to add the watermarks:
Dim watermark_bm As Bitmap = Global.AnchorAuditor.My.Resources.Logo_White
Dim watermark_bm2 As Bitmap = Global.AnchorAuditor.My.Resources.CLS_Logo_White_Engineering
'watermark_bm2.MakeTransparent()
' WATERMARK IMAGE 1 - AA
Using str As Stream = File.OpenRead(s)
Dim or_bm As Bitmap = Image.FromStream(str)
'''''''''''''''''''''''''START IMAGE 1''''''''''''''''''''''''''
or_bm.SetResolution(20, 20)
Dim x1 As Integer = or_bm.Width - 300
Dim Y As Integer = or_bm.Height - 300
Const ALPHA As Byte = 128
' Set the watermark's pixels' Alpha components.
Dim clr As Color
For py As Integer = 0 To watermark_bm.Height - 1
For px As Integer = 0 To watermark_bm.Width - 1
clr = watermark_bm.GetPixel(px, py)
watermark_bm.SetPixel(px, py, _
Color.FromArgb(ALPHA, clr.R, clr.G, clr.B))
Next px
Next py
' Set the watermark's transparent color.
watermark_bm.MakeTransparent(watermark_bm.GetPixel(0, _
0))
' Copy onto the result image.
Dim gr As Graphics = Graphics.FromImage(or_bm)
gr.DrawImage(watermark_bm, x1, Y)
'''''''''''''''''''''''''END IMAGE 1 START IMAGE 2''''''''''''''''''''''''''
or_bm.SetResolution(60, 60)
Dim x2 As Integer = 75
Dim Y1 As Integer = 75
Const ALPHA1 As Byte = 128
' Set the watermark's pixels' Alpha components.
Dim clr1 As Color
For py As Integer = 0 To watermark_bm2.Height - 1
For px As Integer = 0 To watermark_bm2.Width - 1
clr1 = watermark_bm2.GetPixel(px, py)
watermark_bm2.SetPixel(px, py, _
Color.FromArgb(ALPHA1, clr1.R, clr1.G, clr1.B))
Next px
Next py
' Set the watermark's transparent color.
watermark_bm2.MakeTransparent(watermark_bm2.GetPixel(0, _
0))
' Copy onto the result image.
Dim gr1 As Graphics = Graphics.FromImage(or_bm)
gr1.DrawImage(watermark_bm2, x2, Y1)
''''''''''''''''''''''''END IMAGE 2'''''''''''''''''''''''''''
or_bm.Save(s & "deleteme.jpg", _
System.Drawing.Imaging.ImageFormat.Jpeg)
End Using
You're correct - adding a watermark is far easier than removing it. The standard approach is to keep a copy of the original someplace and use that instead of trying to manipulate the image afterwards.

vb.net LED BOARD DISPLAY user control

I am developing LEDBOARD user control in vb.net.I have done it also .Actually its taking too much time to load .In the vb6 same application I am loading 3000 labels using a label control array but not time consuming .In vb.net I am doing same but it's taking too much time to load 3000 labels.Is there any other way(any control or any custom control) to draw input text(any font style),image like below image
It looks like below
Create your LedBoard control from scratch by inheriting from Control, instead of using a UserControl and adding tons of labels.
I just made a little test to show you what I mean. You will have to adapt the logic to meet your needs.
Public Class LedBoard
Inherits Control
Private _rand As Random = New Random()
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.FillRectangle(Brushes.Black, 0, 0, Width, Height)
Const nx As Integer = 40, ny As Integer = 25
Dim w = CInt((Width - 1) / nx) - 1
Dim h = CInt((Height - 1) / ny) - 1
For x As Integer = 0 To nx - 1
For y As Integer = 0 To ny - 1
If _rand.NextDouble() < 0.8 Then
e.Graphics.FillRectangle(Brushes.Red, x * (w + 1) + 1, y * (h + 1) + 1, w, h)
End If
Next
Next
End Sub
End Class