Visual Basic.Net: Drawing Grids With GDI
Sometimes we want to draw grids for various reasons, so this will help explain how to do that.
So lets think.
What are we gonna need to do this?
We will need the following: A procedure(sub-routine) to call when we want to draw the grid.
We will need the procedure to take the following parameters
- The graphics object we will use to render our grid with.
- The point structure that will tell our procedure where the origin of the grid is to be.
- An integer to specify how many columns will be in the grid.
- An integer to specify how many rows will be in the grid.
- A size object to specify the size of the cells(or width of columns and height of rows)
Subroutine
Try to create an empty sub-routine that fills our needs so far. When you are done, you should have something similar to this:
Sub DrawGrid(g As Graphics, origin As Point, rows As Integer, columns As Integer, cellSize As Size)
End Sub
Now that you have taken a moment to compare what you came up with, for simplicities sake, replace your code with the above code.
So how do you think we will use the G, origin, rows, columns, and cellSize parameters?
We are going to use the methods of the g parameter to draw with(this one is easy). But what about the rest of them?
For clarification, in our 2 dimensional circumstance, the origin specifies our x,y center of the grid to be drawn. This means that when we draw the grid, it needs to be exactly centered on our origin. That being said, lets skip ahead for a second, but hold this thought.
The parameters(rows and columns) will specify how many of each(row or column) that we will be drawing.
The cellSize object will specify the columns width, and the rows height.
In order to ensure that when we render the grid it's final place is centered on the origin, we will need to make some calculations. Can you guess what we need to figure out?
We need to figure out the following:
- The leftmost side of the grid(an x1 coordinate)
- The rightmost side of the grid(an x2 coordinate)
- The topmost side of the grid(a y1 coordinate)
- The bottommost side of the grid(a y2 coordinate)
How will we figure these out?
In order to figure this out, we must first know how wide and how tall the grid is going to be.
To calculate the width of the grid, we must multiply the width of each cell or column by the amount of columns we will draw.
To calculate the height of the grid, we must multiply the height of each cell or row by the amount of rows we will draw.
Once we have calculated the total width and height of the grid, we will need to calculate the left, right, top, and bottom most sides of the grid..
Remember, we need to center the grid on the origin.
Center grid
So it is very simple. Center is analogous to half. This means that we can derive a formula. The formulas for calculating the left, right, top, and bottom of the grid are as follows:
- LeftMost = Origin.X - (TotalGridWidth \ 2)
- RightMost = Oriting.X + (TotalGridWidth \ 2)
- TopMost = Origin.Y - (TotalGridHeight \ 2)
- BottomMost = Origin.T + (TotalGridHeight \ 2)
Now take a moment to catch up on all your code. First making your attempt to write it on your own, then comparing the differences, and finally replacing your code with the following code:
Sub DrawGrid(g As Graphics, origin As Point, rows As Integer, columns As Integer, cellSize As Size)
Dim gridWidth As Integer = columns * cellSize.Width
Dim gridHeight As Integer = rows * cellSize.Height
Dim left As Integer = origin.X - (gridWidth \ 2)
Dim right As Integer = origin.X + (gridWidth \ 2)
Dim top As Integer = origin.Y - (gridHeight \ 2)
Dim bottom As Integer = origin.Y + (gridHeight \ 2)
End Sub
Now we have all the information we need to start drawing a grid in the correct place. For drawing lines we will be using a For-Next loop to create 2 points per loop. Specifically, the X1,Y1 and X2,Y2 points needed for the Graphics.DrawLine method, stepping at the cells width or height. Lets now try to accomplish this own, and then compare/replace your code with mine.
Sub DrawGrid(g As Graphics, origin As Point, rows As Integer, columns As Integer, cellSize As Size)
Dim gridWidth As Integer = columns * cellSize.Width
Dim gridHeight As Integer = rows * cellSize.Height
Dim left As Integer = origin.X - (gridWidth \ 2)
Dim right As Integer = origin.X + (gridWidth \ 2)
Dim top As Integer = origin.Y - (gridHeight \ 2)
Dim bottom As Integer = origin.Y + (gridHeight \ 2)
For y As Integer = top To bottom + 1 Step cellSize.Height
Dim pt1 As New Point(left, y)
Dim pt2 As New Point(right, y)
Next
For x As Integer = left To right + 1 Step cellSize.Width
Dim pt1 As New Point(x, top)
Dim pt2 As New Point(x, bottom)
Next
End Sub
Notice how we are using the Top, Bottom, Left, Right integers to specify a range to loop through. Also notice that we are stepping at the cells width or height. One more thing to notice is that in each loop, that the Top, Bottom, Left, or Right values are also used as either x or y constants, this is why it takes two separate loops to draw first horizontal, and then vertical lines. I also added one to the upperbound of the looping ranges. This is a fix for grids with odd sized cells, where without the fix, a line would end up missing in some instances.
Our final task for the DrawGrid method will be to render the lines using the DrawLine method of the graphics object. that was supplied in the parameter of this function. Please note you should use Pens.Black for the pen parameter of the Graphics.DrawLine method.
Lets do that now. You should now have something that looks similar to this:
Sub DrawGrid(g As Graphics, origin As Point, rows As Integer, columns As Integer, cellSize As Size)
Dim gridWidth As Integer = columns * cellSize.Width
Dim gridHeight As Integer = rows * cellSize.Height
Dim left As Integer = origin.X - (gridWidth \ 2)
Dim right As Integer = origin.X + (gridWidth \ 2)
Dim top As Integer = origin.Y - (gridHeight \ 2)
Dim bottom As Integer = origin.Y + (gridHeight \ 2)
For y As Integer = top To bottom + 1 Step cellSize.Height
Dim pt1 As New Point(left, y)
Dim pt2 As New Point(right, y)
g.DrawLine(Pens.Black, pt1, pt2)
Next
For x As Integer = left To right + 1 Step cellSize.Width
Dim pt1 As New Point(x, top)
Dim pt2 As New Point(x, bottom)
g.DrawLine(Pens.Black, pt1, pt2)
Next
End Sub
The only thing left to do is use this method to draw a grid, but for this example we are going to have you add one more line of code right before the very end of the drawGrid method. we are going to have you add a bit of code that will draw the origin onto the grid, so that when you run the sample, you will see that the grid is indeed centered on its origin.
Complete example
Here is a complete example for using the DrawGrid method:
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
Sub DrawGrid(g As Graphics, origin As Point, rows As Integer, columns As Integer, cellSize As Size)
Dim gridWidth As Integer = columns * cellSize.Width
Dim gridHeight As Integer = rows * cellSize.Height
Dim left As Integer = origin.X - (gridWidth \ 2)
Dim right As Integer = origin.X + (gridWidth \ 2)
Dim top As Integer = origin.Y - (gridHeight \ 2)
Dim bottom As Integer = origin.Y + (gridHeight \ 2)
For y As Integer = top To bottom + 1 Step cellSize.Height
Dim pt1 As New Point(left, y)
Dim pt2 As New Point(right, y)
g.DrawLine(Pens.Black, pt1, pt2)
Next
For x As Integer = left To right + 1 Step cellSize.Width
Dim pt1 As New Point(x, top)
Dim pt2 As New Point(x, bottom)
g.DrawLine(Pens.Black, pt1, pt2)
Next
g.DrawEllipse(Pens.Red, New Rectangle(origin.X - 5, origin.Y - 5, 10, 10))
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim origin As New Point(Me.ClientRectangle.Width \ 2, Me.ClientRectangle.Height \ 2)
Dim cellSize As New Size(10, 10)
Dim rowCount As Integer = 10
Dim columnCount As Integer = 10
DrawGrid(e.Graphics, origin, rowCount, columnCount, cellSize)
End Sub
End Class
See Also
Please view my other wiki articles!
An important place to find a huge amount of Visual Basic related articles is the TechNet Wiki itself. The best entry point is Visual Basic Resources on the TechNet Wiki