In der GUI-Programmierung ist es in einigen Fällen sinnvoller, benötigte Steuerelemente automatisch erstellen zu lassen und diese nicht mit dem Form Designer mühselig zu positionieren.
Als Beispiel habe ich ein Programm geschrieben, das für das Zahlenlotto 6 aus 49 einen Tipp-Schein zeigt. Jedes der 49 Felder wird durch ein Button-Objekt symbolisiert.
Es wäre sicherlich mühsam, alle 49 Button-Objekte mit dem Form Designer zu erstellen und zu positionieren.
Deshalb werden alle Button-Objekte im Form_Load
-Event der Form-Klasse erzeugt, mit den notwendigen Eigenschaftswerten versehen (Größe, Position, Beschriftung etc.) und dann dem Controls-Container hinzugefügt.
Das prinzipielle Vorgehen ist:
- Objekt vom gewünschten Steuerelementtyp erstellen:
Button b = new Button(); - grundlegende Eigenschaften des neu erstellten Objekts einstellen; dazu gehören sicherlich Location und Size und vielleicht Text:
b.Location = new Point(50, 100);
b.Size = new Size(50,50);
b.Text = „dynamisch“; - dem Controls-Container für alle Steuerelemente hinzufügen:
Controls.Add(b);
Der Controls-Container, den man in der Designer-Datei findet. enthält alle auf dem Formular darzustellenden Steuerelemente.
Das nachfolgende Bild zeigt das Formular für das (unten beschriebene modifizierte) Lottospiel.
Der nachfolgende Programm-Code zeigt die Vorgehensweise:
using System;
using System.Drawing;
using System.Windows.Forms;
using Lottozahlen;
namespace ControlsAutomatischErstellen
{
public partial class frmMain : Form
{
// Array mit Button-Objekten
Button[] buttons;
const int buttons_per_row = 7;
const int buttons_per_column = 7;
const int distance_left_right = 10;
const int distance_top_down = 10;
Size button_size = new Size(50, 50);
Lotto lotto;
int[] gezogene_zahlen;
int anzahl_lottozahlen = 49;
Color button_default_backcolor = Color.BlanchedAlmond;
Color button_selected_backcolor = Color.Chartreuse;
public frmMain()
{
InitializeComponent();
// Button-Array erstellen
buttons = new Button[anzahl_lottozahlen];
lotto = new Lotto();
}
private void Form1_Load(object sender, EventArgs e)
{
// Es werden Buttons automatisch erstellt und positioniert
this.ClientSize = new Size(buttons_per_row * button_size.Width + (buttons_per_row + 1) * distance_left_right,
buttons_per_column * button_size.Height + (buttons_per_column + 1) * distance_top_down);
// Könnte man auch per x und y berechnen, so ist es einfacher ;)
int i = 0;
for (int y = 1; y <= buttons_per_column; y++)
{
for (int x = 1; x <= buttons_per_row; x++)
{
// Button-Objekt erstellen
Button b = new Button();
b.Size = button_size;
int number = (y - 1) * buttons_per_row + x;
b.Name = "button" + number.ToString();
b.Text = number.ToString();
Point location = new Point((x - 1) * button_size.Width + x * distance_left_right,
(y - 1) * button_size.Height + y * distance_top_down);
b.Location = location;
b.BackColor = button_default_backcolor;
b.Click += new EventHandler(buttons_Click);
// Dem Controls-Container hinzufügen
Controls.Add(b);
// In das Array einfügen
buttons[i] = b;
i++;
}
}
// Alle Buttons sind erstellt
// Nun Lottozahlen ziehen und anzeigen
gezogene_zahlen = lotto.zieheLottozahlen();
färbeButtons();
}
private void färbeButtons()
{
// Jetzt die Hintergrundfarbe der Buttons ändern
for (int i = 0; i < gezogene_zahlen.Length; i++)
{
buttons[gezogene_zahlen[i] - 1].BackColor = button_selected_backcolor;
}
}
private void buttons_Click(object sender, EventArgs e)
{
if (sender is Button)
{
Button b = (Button)sender;
// Hintergrundfarbe der Buttons zurücksetzen
for (int i = 0; i < buttons.Length; i++)
{
buttons[i].BackColor = button_default_backcolor;
}
// Und nun eine neue Ziehung ;)
gezogene_zahlen = lotto.zieheLottozahlen();
färbeButtons();
}
}
}
}
Für das Ziehen der sechs Lottozahlen habe ich eine einfache Klasse namens Lotto.cs
entworfen, die mittels der Methode zieheLottozahlen():int[]
sechs verschiedene Zahlen im Bereich 1 bis 49 zieht und diese als Integer-Array zurückliefert.
Mit Hilfe der beiden Properties AnzahlLottozahlen
und AnzahlZiehungen
lässt sich der Zahlenbereich und die Anzahl der zu ziehenden Zahlen auch variieren. Altenativ existiert eine zweite Konstruktor-Methode, die die beiden Eigenschaftswerte per Parameter einstellt.
Klassendiagramm aus Visual Studio (nicht UML-konform)
Hier der Programmcode:
using System;
namespace Lottozahlen
{
public class Lotto
{
// Array für Lottozahlen
// Index 0 wird nicht verwendet!
// Gezogene Zahlen haben den Wert true
bool[] lottozahlen;
// Ergebnisarray
int[] gezogene_lottozahlen;
public int AnzahlLottozahlen { set; get; }
public int AnzahlZiehungen { set; get; }
// Zufallszahlengenerator
Random lottozahl = new Random();
public Lotto()
{
AnzahlLottozahlen = 49;
AnzahlZiehungen = 6;
lottozahlen = new bool[AnzahlLottozahlen + 1];
gezogene_lottozahlen = new int[AnzahlZiehungen];
}
public Lotto(int lottozahlenanzahl, int ziehungen)
{
AnzahlLottozahlen = lottozahlenanzahl;
AnzahlZiehungen = ziehungen;
lottozahlen = new bool[AnzahlLottozahlen + 1];
gezogene_lottozahlen = new int[AnzahlZiehungen];
}
public int[] zieheLottozahlen()
{
// Ziehen der Lottozahlen
int i = 0;
while (i < AnzahlZiehungen)
{
// Zufallszahl im Bereich von 1 bis 49
int neue_zahl = lottozahl.Next(1, 50);
// neue_zahl ist der Index für das Array
if (!lottozahlen[neue_zahl])
{
// Gezogene Zahl ist noch nicht gezogen worden
lottozahlen[neue_zahl] = true;
// In das Ergebnisarray aufnehmen
gezogene_lottozahlen[i] = neue_zahl;
i++;
}
}
// Ergebnisarray zurück liefern
return gezogene_lottozahlen;
}
}
}
Der nachfolgende Link ermöglicht den Download der Visual Studio Projektmappe.
In der Projektmappe sind drei Projekte, einmal das oben dargestellte, das zweite Projekt ist eine Modifikation des Zahlenlottos „6 aus 49“ (man klickt sechs Zahlen an und erst dann wird eine Ziehung durchgeführt; richtig getippte Zahlen werden dann farbig markiert) und noch ein Projekt mit dem Spiel Tic Tac Toe.