2

I am creating a chess program. And it is composed of sixty four picture boxes with alternating black and white background colours.
I have named them pba1, pba2, pbb1, pbb2, pbc1 and so on.
Now, I want to loop through only the black ones, for example, I want to loop through only, pba1, pbb2, pbc3 and so on.
How do I create a loop for this in VB.NET?

I know of the way to loop through similarly named controls, but I am not able to adapt that method for my problem. Can you tell me a solution?

EDIT: In pba1, pb stands for picture box, and a1 stands for the square. Just in case, you wonder why such a name.

EDIT: Check out this answer

Community
  • 1
  • 1
Rohit Shinde
  • 1,575
  • 5
  • 21
  • 47
  • 1
    Do you have model classes to represent the game state and board separate from the display logic and controls? If not, you should. – mellamokb Jun 23 '12 at 02:39
  • Its winforms. And I don't have classes to represent game state. Its controlled by an array. – Rohit Shinde Jun 23 '12 at 09:24

4 Answers4

6

Loop through the PictureBox's in your ControlCollection and test for BackColor. I used the Form's ControlCollection, if they are in some other type of container control use that.

For Each cntrl As Control In Me.Controls
    If TypeOf cntrl Is PictureBox Then
        If cntrl.BackColor = Color.Black Then
            'Do Something
        End If
    End If
Next

Base on the additional information that you gave in your answer, the reason your example is not working is that the Controls Name is a String and you are comparing it to the PictureBox Control not the Name of the Control.

You can try using the Tag Property instead of the Name of the Control, it will be cleaner and easier to read. I just put a 1 in the PictureBox's Tag Property for Black and a 0 for White.

Private Sub OriginalColour()               
    For Each cntrl As Control In Me.Controls
        Dim result As Integer
        If TypeOf cntrl Is PictureBox Then
            If Integer.TryParse(cntrl.Tag.ToString, result) Then
                If result = 1 Then
                    cntrl.BackColor = Color.Gray
                Else
                    cntrl.BackColor = Color.White
                End If
            End If

        End If
    Next
End Sub
Mark Hall
  • 53,938
  • 9
  • 94
  • 111
  • That does help, but in my program, the possible squares a piece can move has been highlighted. So after moving the piece to one of those, I want to return them to their original colour which will either be black or white. So I can't really check for the backcolor of the picture boxes. So any other solution? – Rohit Shinde Jun 23 '12 at 09:33
  • this gives me an exception when I try it out. – Rohit Shinde Jun 23 '12 at 14:15
  • @RohitShinde What is the exception – Mark Hall Jun 23 '12 at 14:21
  • @RohitShinde See edit, it was hiccuping on non picturebox controls. – Mark Hall Jun 23 '12 at 14:32
  • The exception is that system.windows.form.button cannot be converted to system.windows.form.picturebox – Rohit Shinde Jun 23 '12 at 14:42
  • @RohitShinde Thats what I get for not running my example. I just added another example based on your additional information. I did run it this time :) – Mark Hall Jun 23 '12 at 14:53
4

Generating controls at design time via the Forms Designer only makes sense for layouts which benefit from the forms designer.

In your case, you just have 64 uniform boxes in 8 rows of 8. Don’t use the Forms Designer for this, create the controls at runtime, and don’t give them names like pba1, just put them into an appropriate data structure (such as an 8x8 array):

Private chessFields As PictureBox(8, 8)

' In Form_Load:
For i = 0 To 7
    For j = 0 To 7
        chessFields(i, j) = New PictureBox
        ' Set size, position … then, finally,
        Controls.Add(chessFields(i, j))
    Next
Next

That way, you can access the fields in an orderly fashion without having to go via the Form.Controls collection.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    +1. Step up to a more advanced programming level & follow this advice. – MarkJ Jun 23 '12 at 10:52
  • Yup. I will follow this advice! Thanks!! But another thing, if in this case, I have to access a picturebox, do I simply say, chessfield(i,j).BackColor=Color.Black ? – Rohit Shinde Jun 23 '12 at 11:01
  • @Konrad I used this, but on loading, it is not displaying anything. It remains blank – Rohit Shinde Jun 23 '12 at 14:55
  • Rohit, did you set the `Visible` property of the controls and give them a correct position? – Konrad Rudolph Jun 23 '12 at 16:46
  • I set visible to true. But I couldn't set the location. It couldn't be set. Giving an error. Dunno why. – Rohit Shinde Jun 23 '12 at 17:24
  • 1
    @Rohit That’s not very specific. You probably tried setting `Location.X` and `Location.Y` separately, that doesn’t work. Assign it a `Point`, or set `Top` and `Left` separately. That won’t give an error. – Konrad Rudolph Jun 23 '12 at 17:33
1

Put all the pictureboxes in an 8x8 tableLayoutPanel (also useful for scaling etc). Then

    For Each pb As PictureBox In TableLayoutPanel1.Controls
        Dim col As Integer = TableLayoutPanel1.GetCellPosition(pb).Column
        Dim row As Integer = TableLayoutPanel1.GetCellPosition(pb).Row
        If col Mod 2 = 0 Xor row Mod 2 = 0 Then
            pb.BackColor = Color.Black
        Else
            pb.BackColor = Color.White
        End If
    Next

Of course you could also use an array of the squares if you have that available.

This will not affect the events (pba1.click etc).

Rur
  • 25
  • 6
Rur
  • 11
  • 1
  • Will this affect my click events which I have already coded? I mean, I have already written some code for all the picture boxes. So if I put my picture boxes in a tableLayoutPanel, will the code or its functioning be affected? – – Rohit Shinde Jun 23 '12 at 14:58
0

This is fairly simple and it may be resource heavy, but it works. I have a form with 36 CheckBoxes. This takes advantage of the fact that when you copy a checkbox it just increases the number of the name. I ended up with 36 checkboxes named CheckBox1 thru Checkbox36. The Function returns a checkbox, which may be used to set or read any property.

Private Function GetCheckBox(ByVal Index As Integer) As CheckBox
    Dim CKBox As checkbox
    For Each cntrl As Control In Me.Controls
        If TypeOf cntrl Is CheckBox Then
            CKBox = cntrl
            If CKBox.Name = "CheckBox" & Index Then
                Exit For
            End If
        End If
    Next
    Return ckbox
End Function