Newsgroup: it.comp.lang.visual-basic
Titolo: [!][LONG]Primo indice libero di una matrice di controlli

Se ne parlava in qualche post piu' sotto: "Come spostarsi da
un textbox all'altro senza il tasto TAB?".
Ecco due versioni scritte al volo (la seconda piu'
performante della prima poiche' usa il For Each) per
ricavare l'indice data una matrice di controlli:
Private Function PrimoIndiceLiberoForTo( _
                    ByRef MatriceDiControlli As Object)
    Dim i As Long
    Dim LastIndex As Long
    With MatriceDiControlli
        If Not .Item(0).Visible Then
            PrimoIndiceLiberoForTo = 0
        ElseIf .UBound < .Count Then
            PrimoIndiceLiberoForTo = .Count
        Else
            For i = .LBound To .UBound
                On Error Resume Next
                If .Item(i).Index > LastIndex + 1 Then
                    Exit For
                End If
                If Err.Number = 340 Then
                    Err.Clear
                    Exit For
                Else
                    Err.Raise Err.Number, _
                              Err.Source, _
                              Err.Description, _
                              Err.HelpFile, _
                              Err.HelpContext
                End If
                LastIndex = .Item(i).Index
            Next i
            On Error GoTo 0
            PrimoIndiceLiberoForTo = i
        End If
    End With
End Function
Private Function PrimoIndiceLiberoForEach( _
                    ByRef MatriceDiControlli As Object)
    Dim Controllo As Object
    Dim LastIndex As Long
    With MatriceDiControlli
        If Not .Item(0).Visible Then
            PrimoIndiceLiberoForEach = 0
            Exit Function
        ElseIf .UBound < .Count Then
            PrimoIndiceLiberoForEach = .Count
            Exit Function
        End If
    End With
    For Each Controllo In MatriceDiControlli
        On Error Resume Next
        If Controllo.Index > LastIndex + 1 Then
            Exit For
        End If
        If Err.Number = 340 Then
            Err.Clear
            Exit For
        Else
            Err.Raise Err.Number, _
                      Err.Source, _
                      Err.Description, _
                      Err.HelpFile, _
                      Err.HelpContext
        End If
        LastIndex = Controllo.Index
    Next Controllo
    On Error GoTo 0
    PrimoIndiceLiberoForEach = LastIndex + 1
End Function
Per provarle inserite una Label (lblTest) con indice 0 ed
invisible in cima al form, e due Command Button
(cmdCaricaForTo e cmdCaricaForEach).
Di seguito un po' di codice di appoggio.
Sub generica che, data una matrice di controlli qualunque e
l'indice dell'elemento da caricare, carica il controllo e lo
visualizza subito sotto al precedente:
Private Sub CaricaControllo(ByRef MatriceDiControlli As
Object, _
                            ByVal Index As Long)
    With MatriceDiControlli
        If Index > 0 Then
            Load MatriceDiControlli(Index)
            .Item(Index).Top = .Item(Index - 1).Top + _
                               .Item(Index - 1).Height
            .Item(Index).Left = .Item(Index - 1).Left
        End If
        .Item(Index).Caption = "Controllo " & CStr(Index)
        .Item(Index).Visible = True
    End With
End Sub
La corrispondente per scaricare il controllo:
Private Sub ScaricaControllo(ByRef MatriceDiControlli As
Object, _
                             ByVal Index As Long)
    If Index > 0 Then
        Unload MatriceDiControlli(Index)
    Else
        MatriceDiControlli(Index).Visible = False
    End If
End Sub
Il codice per i Command Button:
Private Sub cmdCaricaForTo_Click()
    Call CaricaControllo(lblTest,
PrimoIndiceLiberoForTo(lblTest))
End Sub
Private Sub cmdCaricaForEach_Click()
    Call CaricaControllo(lblTest,
PrimoIndiceLiberoForEach(lblTest))
End Sub
Per scaricare una Label doppio click sulla stessa:
Private Sub lblTest_DblClick(Index As Integer)
    Call ScaricaControllo(lblTest, Index)
End Sub
Felice di dare chiarimenti e di ricevere commenti o
suggerimenti per migliorare il codice sopra.
Happy Coding =)
Lokar
--
Sito Comune: 
http://www.it-lang-vb.net/
Manifesto: 
http://www.it-lang-vb.net/docs/Manifesto.txt
UGIdotNET - 
http://www.ugidotnet.org

         On Error Resume Next
Solo letto, non provato.
quel gestore di errori, che significato ha? (a parte quello scaramantico di
"non si sa mai")
Con il ciclo for each non si dovrebbe verificare nessun errore....
Però.... sicuramente avrai fatto le tue prove, e io no, ma siamo sicuri che
il ciclo for each restituisca gli elementi con l'indice in ordine?
Per spiegarmi meglio: se io metto aggiungo prima il controllo con indice 2,
poi quello con indice 1, nel ciclo for each in che ordine vengono
restituiti? Di indice o di inserimento?
Salutoni
Sergio

 restituisca gli elementi con l'indice in ordine?
Ottima osservazione e bella domanda. :D
Ho dato per scontato che fossero per indice (e dalla
moltitudine di prove che ho fatto... i conti tornano), pero'
effettivamente non ho la certezza che il For Each li
restituisca in ordine di indice.
Grazie,


 E perche' no? :)
Perchè sono pigro ;-)
Il pc connesso a internet non ha il vb6 (nè nessun altro ambiente di
sviluppo :-( ) per cui dovrei copiare il codice su dischetto, alzarmi dalla
seggiola, fare 2 metri di strada (per girare intorno alla scrivania, in
linea d'aria sono circa 50 cm), caricare il codice sul pc "di sviluppo"
eccetera.
Decisamente troppo faticoso, per la mia indole.
Salutoni
Sergio