3

In a Visual Basic 2010 form application I have the below code snippet:

For Each ctlControl In Me.Panel1.Controls
    If TypeName(ctlControl) = "PictureBox" Then
        ctlControl.image = Nothing
    End If
Next ctlControl

My problem is when it loops through the controls it does not start with the top left control and it seems to go over each picture box in random order.

How do I control the order of which picture box is updated next. Is there a property similar to tab index(in VB 6) which I can manipulate to control the order in which picture boxes are updated by my loop?

Dean
  • 1,226
  • 2
  • 20
  • 39
  • Is it going by the TabIndex property? – George Jan 02 '13 at 22:07
  • No, just need them to be processed in order – Dean Jan 03 '13 at 08:30
  • How are picture boxes are being added to the form: is it dynamically through code or are they static and were added through IDE? If dynamically, then I'd recommend using control arrays. – George Jan 03 '13 at 14:53
  • @George, static added via the IDE – Dean Jan 07 '13 at 05:28
  • 1
    in that case, you can still make it a control array, place it sequentially the way you want and then reference each PictureBox with a simple for loop. If you originally placed them in the right order (first in the top left, etc) then if you go from 0 and up, you should loop through controls in proper order. – George Jan 07 '13 at 15:25

4 Answers4

2

As a more proper and sure way, I would get each picture box, keep handles and locations of them, then sort them according to their location. Now they are ready to use. Here is an example:

Public Class Form1
    Structure Pbox
        Dim handle As IntPtr
        Dim top As Integer
        Dim left As Integer
    End Structure
    Dim pboxlist As New List(Of Pbox)
    Sub ClearImages()
        pboxlist.Clear()
        For Each c As Control In Me.Controls
            If TypeName(c) = "PictureBox" Then
                Dim x As New Pbox
                x.top = c.Top
                x.left = c.Left
                x.handle = c.Handle
            End If
        Next
        pboxlist.OrderByDescending(Function(a) a.top).ThenByDescending(Function(a) a.left)
        For Each item In pboxlist
            Dim x As PictureBox = PictureBox.FromHandle(item.handle)
            x.Image = Nothing
        Next
    End Sub
End Class

Another approach is using a good naming, so that you can use their names to sort them. For instance, PictureBox1 will come before PictureBox2 if you sort. So you should use PictureBox1 for the very top and left one and PictureBox2 for the next one and so on...

EDIT: Using Tag property, as John Bustos suggested, instead of names is an easier and better idea. So without getting lost in names, you can sort picture boxes according to their Tags which are defined by you.

gunakkoc
  • 1,069
  • 11
  • 30
  • 1
    As an add on to this - Awesome answer, btw, @theGD, you could always assign your pictureboxes numbers in the `Tag` property and use that for sorting rather than location if that serves your purpose better. – John Bustos Jan 02 '13 at 23:21
  • Considering that my Picture Boxes are actually named PictureBox1, PictureBox2, ...,... Using the name would serve me better. Would I still need to put them in a list to sort them or there is a quicker way? @GunDeniz – Dean Jan 03 '13 at 08:31
  • Yes. But I would go with the first one. Since it works regardless of tag and name property, only location based. – gunakkoc Jan 03 '13 at 10:51
  • Thanks, il try it out and let you know how it goes – Dean Jan 03 '13 at 11:29
0

The order of the controls was determined by the order they were added to the panel and not tabstop index. You can change that by carefully reorganizing the order they were added to the panel in the form's designer file, though I'd not recommend it.

U1199880
  • 907
  • 1
  • 10
  • 21
0

As some of the other guys have said you could use the TAG property which is probably the BEST shot, whenyou are dynamically creating the picture boxes use a counter and add the counter value to the TAG property. if you added the picture boxes manually then simply start with the top left and work towards the right and add a value in the TAG property field of each one starting with 1 and increasing by one each time and continue until the row is completed then carry on with the next row.

Finally when your ready to loop through the picture boxes simply follow the pattern below..

'Calc number of picture boxes
For Each ctlControl In Me.Panel1.Controls
  If TypeName(ctlControl) = "PictureBox" Then
    Counter = Counter + 1
  End If
Next ctlControl
ThisBox = 1
Do
  For Each ctlControl In Me.Panel1.Controls
    If TypeName(ctlControl) = "PictureBox" Then
      If CInt(ctlControl.Tag) = ThisBox Then 
        CLEAR-YOUR-IMAGE-HERE
        ThisBox = ThisBox + 1
      End If
    End If
  Next ctlControl
Loop Until ThisBox = Counter

Note: Its IMPORTANT your numbers that you place in the TAG property are consecutive or you will become forver stuck in the DO-LOOP!!!

Zeddy
  • 2,079
  • 1
  • 15
  • 23
  • My problem with using the tag property is that the tag property is being used as a text representation of what is shown in the picture box. I will try your suggestion using the name property instead. I will let you know how it goes. – Dean Jan 03 '13 at 11:27
  • I dontthink its a good idea to use the name property as it is used to identigy th picturebox or object. maybe you could PREFIX the textual description of the picture such as instead of forr example.... Photo of bob ... [1] Photo of bob or ..... instead of By the seaside... [2] By the seaside.... and that way you know the identification number is within the SQUARE brackets – Zeddy Jan 03 '13 at 23:28
0

The PictureBox control has a Text property you can use instead of Tag.

It doesn't come up in Intellisense because it's an infrastructure property, but it's there.

http://msdn.microsoft.com/en-us/library/hc9k45f4(v=vs.110).aspx

(I wanted to comment on Zaf Khan's answer but I don't have the rep, yet.)

ourmandave
  • 1,505
  • 2
  • 15
  • 49