Den Code, den ich geschrieben und erklärt habe, deckt die Kernfunktionen des Programmes ab - neues Bild anzeigen, aktuelles Bild entfernen, das Ganze vorbereiten. Damit man es aber wirklich zu einem funktionierenden Programm machen kann, müssen die Teile an die richtigen Stellen im Programm kopiert werden und eventuell noch einige If-Abfragen rein (wie z.B. eine, die dafür sorgt, dass das Programm aufhöhrt, wenn alle Bilder abgearbeitet wurden).
Du hast letztlich den gesamten Code in den Form1_Load-Sub kopiert. Das Programm würde dann beim Start diesen Code einmalig ausführen und danach nichts mehr tun. (Der Fehler resultiert daher, dass in der ComboBox nichts ausgewählt ist (was ja auch nicht der Fall sein kann, da das Programm erst noch gestartet wird) - der Codeteil zum Entfernen des Bildes, wo der Fehler auftritt, ist dafür gedacht dann ausgeführt zu werden, wenn der Benutzer eine Auswahl getätigt hat und den Button klickt.)
Tatsächlich muss der vorbereitende Code nur einmal bei Programmstart ausgeführt werden - ist also dort, wo er ist, gut aufgehoben. Die anderen Teile müssen aber wo anders hin. So muss der Code, der das aktuelle Bild entfernt, dann aufgerufen werden, wenn der Benutzer den Button klickt und direkt danach der Code, der ein neues Bild anzeigt. Diser Code muss aber auch ganz am Anfang einmal ausgeführt werden, damit das erste Bild angezeigt wird.
Ich hoffe es ist nicht zu schlimm, wenn ich das ganze etwas ausschweifender erkläre. Wenn ich es aber jetzt richtig erkläre, hast du irgendwann später vielleicht auch noch Nutzen davon.
In Visual Basic werden Benutzeroberflächen Ereignis-gesteuert programmiert. Wenn der Benutzer einen Button klickt wird ein sogenanntes Ergeignis automatisch ausgelöst. Da man oft sein Programm nur dann Dinge tun lassen will, wenn der Benutzer mit dem Programm interagiert, er also z.B. auf einen Button klickt, können wir solche Ereignisse „behandeln“, was bedeutet, wir schreiben Code, der ausgeführt wird, wenn das Ereignis eintritt. Dafür braucht man Ereignisbehandler, welche meistens diese Form haben:
Private Sub STEUERELEMENT_EREIGNIS(sender As System.Object, e As System.EventArgs) Handles STEUERELEMENT.EREIGNIS
Zum Beispiel kann unser Steuerelement, dass das Ereignis auslöst, ein Button sein (Button1 wäre ein möglicher Name eines solchen Buttons) und das Ereignis könnte das Klick-Ereignis des Buttons sein, also Click. Wenn du einen Button einfügt in den Form-Designer und dann doppelt auf diesen klickst landest du ja im Code-Editor - aber nicht irgendwo, sondern in einem neu erstellten (falls noch nicht vorhandenem) Ereignisbehandler dieses Buttons.
Diese Ereignisbehandler sind die Dinge, die du glaube ich mit „Fenster“ in deiner vorigen Antwort meintest. Und wenn du eben Code in den Ereignisbehandler Button1_Click schreibst, wird der Code jedesmal und nur dann ausgeführt, wenn der Benutzer auf den Button klickt.
Es gibt noch mehr Ereignisse. Ein Button allein hat viele Ereignisse („Click“, das ist das Standard-Ereignis, aber auch „DoubleClick“, „MouseDown“ (ausgelöst, wenn die Maus auf dem Button heruntergeklickt wird; Click würde nur ausgelöst werden, wenn die Maustaste auch losgelassen wird, usw.) und nicht nur Button haben Ereignisse, sondern z.B. auch die Form, also das ganze Fenster wo du deine Buttons und andere Dinge platzierst. Die Form hat z.B. das Load-Ereignis - das wird ausgelöst, wenn die Form geladen wird (vereinfacht: das Programm geladen wird). Zu diesem kommst du durch Doppelklick auf die Form selbst und das ist auch der Ergenisbehandler, in den du den gesamten Code reinkopiert hattest (Form1_Load).
Also, der vorbereitende Code muss ausgeführt werden, wenn das Programm startet - das Load-Ereignis der Form beitet sich da an. Steht also schon richtig. Der Teil, der ein neues Bild anzeigt, muss am Anfang natürlich auch einmal durchlaufen werden. Deswegen steht dieser auch richtig - noch in Form1_Load, aber nach dem Teil mit der For-Schleife. Was ich hier übrigens vergessen habe: Ein Aufruf, der den Zufallszahlengenerator initialisiert. Ich weiß nicht, ob man diesen auch weglassen kann, zur Sicherheit kannst du ihn aber hinschreiben:
Randomize()
Diese Zeile einfach nach der For-Schleife einfügen (also nach dem Next, das das Ende der Schleife markiert, aber noch vor dem Aufruf, das erste Bild anzuzeigen (da wir dort bereits eine Zufallszahl brauchen).
Der Teil, der das Bild entfernt (die bei dir vier Zeilen mit den vielen "Remove"s), darf aber nicht in Form1_Load, also rauslöschen. Stattdessen muss dieser in das Click-Ereignis des Buttons, so dass das nur ausgeführt wird, wenn der Button geklickt wird. Also muss es in Button1_Click. Hierbei hatte ich aber einen Fehler gemacht bzw. war ich etwas ungenau; für den allgemeinen Fall funktioniert das nicht:
ComboBox1.Items.RemoveAt(ComboBox1.SelectedIndex)
Denn das würde das aktuell ausgewählte Element aus der ComboBox entfernen - das wäre korrekt, falls der Benutzer richtig geraten hat, aber falls er falsch riet, wäre es blöd, wenn der von ihm fälschlicherweise ausgewählte Begriff entfernt wird. Deswegen müssen wir das zu entfernende Element - den richtige Begriff - aus der ComboBox löschen, indem wir ihn der Remove-Funktion der ComboBox übergeben. Diesen Namen des Bildes müssen wir uns aber erst „erarbeiten“ - die Variable bildname können wir deswegen nicht nehmen, da sie hier in diesem Bereich garnicht definiert ist. Variablen sind im Allgemeinen nur innerhalb des Abschnittes gültig, in dem sie definiert werden. EIn solcher Abschnitt ist z.B. die For-Schleife. Außerhalb der For-Schleife gibts diese Variable also nicht mehr. Auch gibt es die Variable bildpfad nicht mehr, also machen wir uns beide neu.
Das erstellt die bildpfad-Variable:
Dim bildpfad As String
Den Pfad des Bildes können wir uns aus der ImageLocation-Eigenschaft der PictureBox1 holen, denn dort wird ja unser aktuelles Bild noch angezeigt.
bildpfad = PictureBox1.ImageLocation
Und jetzt erstellen wir uns daraus wieder unseren Bildnamen.
Dim bildname As String
bildname = bildpfad.Substring(pfad.Length + 1)
bildname = bildname.Substring(0, bildname.Length - 4)
Mit bildname können wir ihn jetzt azs der ComboBox entfernen.
ComboBox1.Items.Remove(bildname)
Deren Auswahl sollten wir direkt danach auf das erste Element (in der Programmierung zählt man meist mit 0 beginnend) festlegen, sonst ist evtl. garnichts ausgewählt.
ComboBox1.SelectedIndex = 0
Und aus der bilder-Variable können wir auch das entsprechende Bild entfernen. Aber mit bildpfad, nicht mit bildname, da in bilder ja alle Bildpfade gespeichert sind.
bilder.Remove(bildpfad)
Das, was ich gerade an Code geschrieben habe (von „Dim bildpfad As String“ an), kannst du als Lösch-Funktion verwenden. Das, was ich in meiner ersten Antwort geschrieben hatte, funktioniert nicht im Allgemeinen.
Wir haben also jetzt in Button1_Click die Lösch-Funktion. Dort hinein muss aber auch der Teil, der ein neues Bild anzeigt, aber natürlich nach dem das aktuelle Bild entfernenden Teil. Letztlich haben wir den Code zum Anzeigen eines neuen Bildes dann am Ende zweimal, einmal in Button1_Click und einmal in Form1_Load.
Noch eine Sache, die fehlt: Damit der Code der Lösch-Funktion funktioniert, musst du den Teil, der den Pfad zu den Bildern speichert, vor die Form1_Load setzen, damit wir auf pfad auch später noch zugreifen können.
Zu deiner Frage, warum man den Pfadnamen fest im Code angibt: Du hast recht, es ist besser, so eine Sache wie den Pfad variabel zu halten. Ich wusste nur nicht, was für dich einfacher ist. Wenn du willst, dass dieser beim Start des Programmes eingegeben werden muss, kannst du es beispielsweise so machen, dass du in Form1_Load folgender Zeile schreibst:
pfad = InputBox(„Pfad angeben“)
Das muss dann aber als aller erstes in Form1_Load stehen. Gleichzeitig ist es dann sinnlos, der pfad-Variable ganz oben (noch vor der Form1_Load, wo wir sie ja gerade hinversetzt haben) einen Wert zuzuweisen, also löschst du dort einfach das " = „“", das direkt hinter „Dim pfad As String“ steht.
Jetzt hätten wir das Programm soweit, dass es prinzipiell erstmal funktioniert. Was wir noch machen können/müssen ist den Fall zu betrachten, wenn der Benutzer das letzte Bild bearbeitet hat, sowie eventuell mitzuzählen wie viele richtige er hat. Aber am besten wir bekommen diesen Teil erstmal zum Laufen - das Programm kann dann bereits getestet werden - bevor wir weitermachen.