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