Frage von Zetesafe, 48

Visual Basic - Varaiblen Namen für ein Element?

Hallo,

Ich habe 64 Pictureboxen die mit A1 bis H8 beschriftet sind [Beschriftung und Anordnung wie bei einem Schachfeld]. Jetzt möchte ich dass das Programm sich die Namen selbst errechnet und dann immer die Farbe der jeweiligen Picturebox in Blau ändert. Das mit dem ausrechnen ist kein Problem aber der Befehl zum Umfärben funktioniert nicht. Weiß jemand was ich falsch mache?

(Buchstabenvariable & Zahlenvariable).BackColor = Color.Blue

Danke schonmal

Antwort
von horstfh, 13

Schau Dir mal meinen Vorschlag an.

Ich habe ein kleines Programm geschrieben, mit dem Du Deine Probleme sicher lösen kannst.

  Const ZeilenMax As Short = 7
Const Spaltenmax As Short = 7
Private PB(ZeilenMax, Spaltenmax) As PictureBox

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Zuordnen()
NUD1.Maximum = ZeilenMax
NUD2.Maximum = Spaltenmax
End Sub
' ------------------------------
Sub Zuordnen()
PB(0, 0) = PictureBox1
' usw .......... bis
PB(7, 7) = PictureBox64
End Sub

' ------------------------------
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
setFocus(sender)
End Sub
' usw .......... bis
Private Sub PictureBox64_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox64.MouseDown
setFocus(sender)
End Sub

' -----------------------------

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
SetBColor(NUD1.Value, NUD2.Value)
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
PB_Clear()
End Sub

' -----------------------------

Sub SetBColor(ByVal Z As Short, ByVal S As Short)
If PB(Z, S).BackColor = Color.Blue Then
PB(Z, S).BackColor = Color.White
Else
PB(Z, S).BackColor = Color.Blue
End If
End Sub

Sub PB_Clear()
For Z As Short = 0 To ZeilenMax
For S As Short = 0 To Spaltenmax
PB(Z, S).BackColor = Color.White
Next
Next
End Sub

Sub GetCoord(ByVal PBx As PictureBox, ByRef Zeile As Short, ByRef Spalte As Short)
For S As Short = 0 To Spaltenmax
For Z As Short = 0 To ZeilenMax
If PB(Z, S) Is PBx Then
Zeile = Z
Spalte = S
Exit Sub
End If
Next
Next
End Sub

Sub setFocus(ByVal sender As PictureBox)
Dim Zeile, Spalte As Short
GetCoord(sender, Zeile, Spalte)
PB(Zeile, Spalte).Focus()
SetBColor(Zeile, Spalte)
End Sub


Ein bisschen Aufwand (64 mal jeweils) liegen in dem Anordnen der PictureBoxen, in Zuordnen und den PictureBox~_MouseDown 

Gruß Horst

Kommentar von Zetesafe ,

Ach du meine Güte. Da hast du dir ja richtig Arbeit gemacht um mir zu helfen. Vielen vielen Dank. Ich schaue gleich mal dass ich das eingebaut kriege.

Antwort
von NoHumanBeing, 28

Ich würde die Steuerelemente (Pictureboxen) zur Laufzeit per Code erzeugen (also "new System.Windows.Forms.PictureBox()", und dann Eigenschaften setzen), anstatt mit dem Designer.

Dann kannst Du die einzelnen Elemente (z. B. mittels zwei geschachtelter For-Schleifen, die jeweils von 0 bis 7 (für 8 Durchläufe) laufen), in ein (zweidimensionales) Array packen und über die Array-Indizes (0 ... 7, 0 ... 7) ansprechen.

Wenn Du nicht zwei numerische Indizes, sondern einen Buchstaben und eine Ziffer haben möchtest, dann musst Du den Buchstaben eben entsprechend "parsen". Das würde ich wie folgt umsetzen.

  1. Prüfen, ob der String überhaupt zwei Zeichen lang ist. Wenn nicht, irgendwie geeignet abbrechen (z. B. None zurückgeben). Wenn ja, fortfahren.
  2. Erstes Zeichen aus dem String extrahieren.
  3. In Lowercase umwandeln (damit es egal ist, ob man 'a' oder 'A' angibt).
  4. ASCII-Wert des Zeichens herausfinden und überprüfen, ob er zwischen 'a' und 'h' (jeweils einschließlich, also ">=" und "<=" als Vergleichsoperatoren) liegt. Wenn nicht, abbrechen wie oben, sonst fortfahren.
  5. Den Character 'a' abziehen (damit 'a' = 0, 'b' = 1, ...).
  6. Das Ergebnis dieses Vorgangs in einer Variable "idx_first" vom Typ Integer speichern.
  7. Zweites Zeichen aus dem String extrahieren.
  8. ASCII-Wert des Zeichens herausfinden und überprüfen, ob er zwischen '0' und '9' (jeweils einschließlich, also ">=" und "<=" als Vergleichsoperatoren) liegt. Wenn nicht, abbrechen wie oben, sonst fortfahren.
  9. Den Character '0' abziehen (damit '0' = 0, '1' = 1, ...).
  10. Das Ergebnis dieses Vorgangs in einer Variable "idx_second" vom Typ Integer speichern.
  11. Das Array, das Deine Steuerelemente enthält, an der Stelle (idx_first, idx_second) indizieren. Damit erhältst Du Zugriff auf das entsprechende einzelne Steuerelement. Dann eine Methode aufrufen oder eine Eigenschaft ändern.

Kommentar von Zetesafe ,

Vielen Dank für die Antwort.

Kommentar von NoHumanBeing ,

Keine Ursache! :-)

Antwort
von safur, 23

Beispiel: frmInput.Controls("txtInput" & i) = i

Bei dir könnte es dann so aussehen
UserForm1.Controls("A" & i).BackColor = Color.Blue

Kommentar von NoHumanBeing ,

Ja, das sollte auch funktionieren.

Allerdings würde ich Elemente nicht wirklich über einen Namen ansprechen wollen. Der Name eines Controls sollte eigentlich mehr oder weniger belanglos sein und könnte durchaus auch "pictureBox1", "pictureBox2", ... lauten. Und die Zahlen hängen dann auch noch davon ab, in welcher Reihenfolge man die Controls hinzugefügt hat.

Ja, ich bin mir bewusst, dass man den Namen explizit vergeben kann, aber der Name ist für mich ein absolutes Implementierungsdetail (letztlich ist es ja ein Variablenname) und nichts, worüber ich ein Control, das sich in einer regelmäßigen Anordnung befindet, tatsächlich "adressieren" wollen würde.

Aber das ist nur mein Empfinden. Funktionieren wird es durchaus auch so. Der Code ist eben nicht sonderlich "wartbar".

Kommentar von safur ,

Hmm, NoHumanBeing

Du musst aber auch mal sehen, viele hier haben keine Informatik studiert oder sind gelernter Programmierer. Sie würden deinen Voschlag garnicht verstehen :-)

Ich würde mir ggf. auch ein zwei-dimensionales-Array erzeugen. Meine Felder würden nur 0, 1, 2, usw heißen :-)

Was ich mir auch gut vorstellen kann, man erzeugt einen eigenen Type als Array.
Darin hat man die Eigenschaften des Feldes. (weiß, schwarz) (wie die Reihe A, B, C, D .. heißt) usw.

Kommentar von CrystalixXx ,

So ein 2-dimensionales Array ist schon sinnvoll, aber 64 PictureBox-Steuerelemente sind ein grundlegend falscher Ansatz. Dann doch lieber ein eigenes Steuerelement mit DoubleBuffered im Schachbrettmuster und ähnlicher Logik. Die Darstellung erfolgt dann in der OnPaint-Methode.

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten