In the last post, I explained how to draw the lines for a grid. Keep in mind we are currently building just one section of the sudoku puzzle; this is so we can learn to make reusable code.
On the designer portion of the custom control, I just dragged nine labels into the view. It’s kind of messy:
Nine labels for nine numbers.
There are probably a few different ways to store these numbers, but instead of declaring nine different integers, I declared one single string. To make the code bigger, press Ctrl+Scroll Mouse Wheel Up
Private _AllNumbers As String = "123456789" Public ReadOnly Property AllNumbers As String
Get
Return _AllNumbers
End Get End Property
The property is for exposure outside the control. The only manipulation of the numbers will come from inside the control, and will edit the string directly. Since every square will have a single digit as a value, I decided to use the string’s array behavior to my advantage. The number at position one will be _AllNumbers(0), the second will be at position (1) and so on. I could have used an integer array, but then I would have had to use initialization code, and besides, an integer is 32 bits in size, while a single character is 8 bits. The total size of a string is 80 bits, while an integer array would have been 320 bits.
Now we need to link the values in the string to the values of the labels. We also need to position the labels using the same technique we used to position the strings; this involves measuring Me.Width and Me.Height.
For this, I added a few more lines to the OnPaint() sub:
For Each ctrl As Control In Me.Controls
Dim indivLabel As Label = TryCast(ctrl, Label)
If Not IsNothing(indivLabel) And ctrl.Name.StartsWith("lbl") Then ' I use "lbl" at the beginning of every label's name
Dim mySize As New System.Drawing.SizeF
Dim myFont As New System.Drawing.Font(indivLabel.Font.FontFamily, indivLabel.Font.Size)
mySize = e.Graphics.MeasureString(indivLabel.Text, myFont)
indivLabel.Width = CType(Math.Round(mySize.Width, 0), Integer)
End If
Next
lblTopLeft.Location = New System.Drawing.Point(firstHorizontalLinePositionX / 2 - 7, firstVerticalLinePositionY / 2 - 7)
lblTopMiddle.Location = New System.Drawing.Point((firstHorizontalLinePositionX + secondHorizontalLinePositionX) / 2 - 5, firstVerticalLinePositionY / 2 - 7)
lblTopRight.Location = New System.Drawing.Point((secondHorizontalLinePositionX + Me.Width) / 2 - 7, firstVerticalLinePositionY / 2 - 7)
lblMiddleLeft.Location = New System.Drawing.Point(firstHorizontalLinePositionX / 2 - 7, (firstVerticalLinePositionY + secondVerticalLinePositionY) / 2 - 7)
lblMiddleMiddle.Location = New System.Drawing.Point((firstHorizontalLinePositionX + secondHorizontalLinePositionX) / 2 - 5, (firstVerticalLinePositionY + secondVerticalLinePositionY) / 2 - 7)
lblMiddleRight.Location = New System.Drawing.Point((secondHorizontalLinePositionX + Me.Width) / 2 - 7, (firstVerticalLinePositionY + secondVerticalLinePositionY) / 2 - 7)
lblBottomLeft.Location = New System.Drawing.Point(firstHorizontalLinePositionX / 2 - 7, (secondVerticalLinePositionY + Me.Height) / 2 - 7)
lblBottomMiddle.Location = New System.Drawing.Point((firstHorizontalLinePositionX + secondHorizontalLinePositionX) / 2 - 5, (secondVerticalLinePositionY + Me.Height) / 2 - 7)
lblBottomRight.Location = New System.Drawing.Point((secondHorizontalLinePositionX + Me.Width) / 2 - 7, (secondVerticalLinePositionY + Me.Height) / 2 - 7)
If this code doesn't show on your monitor, you can download it from the link at the end of this post. It checks the size of the text in
a given label, then resizes the label based on that. This is useful if you decide to change the font of the text, I don't think Courier New
is going to be suitable in all cases. The code that relocates the labels uses the variables that were declared to draw the lines. Every
label is located at the average of one line and the next, or in other words "the middle."
The code to link the value in _AllNumbers with the labels is pretty straightforward:
lblTopLeft.Text = _AllNumbers(0)
lblTopMiddle.Text = _AllNumbers(1)
lblTopRight.Text = _AllNumbers(2)
lblMiddleLeft.Text = _AllNumbers(3)
lblMiddleMiddle.Text = _AllNumbers(4)
lblMiddleRight.Text = _AllNumbers(5)
lblBottomLeft.Text = _AllNumbers(6)
lblBottomMiddle.Text = _AllNumbers(7)
lblBottomRight.Text = _AllNumbers(8)
Here is what the application will look like when you build it:
In the next post, we will look at using event handlers to change the value of the number when you click on it. We also might start into some Sudoku logic to check if any number is repeated within the control.
As always, you can download the source code here.

