Windows Forms

Dieser Beitrag ist ein Tutorial für die Erstellung eines simplen Taschenrechners mit Benutzeroberfläche. Wenn du meine bisherigen Beiträge durchgearbeitet hast, bist du mit den Grundlagen wie Schleifen, Variablen, Switch Case Anweisungen, Stringverarbeitung, Datentypen, Arrays und Vergleichsoperatoren bereits vertraut. Falls nicht empfehle ich dir, das erst nachzuholen, am besten mit dem ersten Beitrag, bevor du dir mit der zusätzlichen Komponente „Benuteroberfläche“ erhöhte Komplexität erzeugst. Dieses Beispiel ist mit Hilfe von Visual Studio in C# und mit Nutzung der Windows Forms Technologie erstellt worden. Natürlich kann auch eine andere Entwicklungsumgebung hierfür genutzt werden.

  1. Inhalt
  2. Windows Forms was ist das
  3. Windows Forms Projekt erstellen
  4. Aufbau einer Windows Forms Anwendung
  5. Ausführen der Anwendung
  6. Der Entwurfsmodus
  7. Die Oberfläche designen
  8. Events nutzen
  9. Logik implementieren
  10. Einsatzempfehlung
  11. Codedownload (kostenlos)

Windows Forms was ist das?

Windows Forms ist eine Art GUI (graphical user interface) Werkzeugkasten zum Erstellen von Programmen, die eine grafische Benutzeroberfläche haben, auf der Basis des .NET Frameworks. Also die klassischen Windows (Fenster) Anwendungen inklusive des gewohnten Windows-Designs.

Mit Windows Forms werden so genannte Smart Clients entwickelt. Smart Clients sind einfach zu entwickeln, upzudaten, können mit oder ohne Verbindung zum Internet genutzt werden und greifen auf lokale Ressourcen auf einer sichereren Art zu, als traditionelle Windows basierte Applikationen. Windows Forms gibt es schon lange, ein konkurrierendes neueres Framework ist WPF (Windows Presentation Foundation) dies bietet eine einfache zweiseitige Datenbindung an die Steuerelemente der Benutzeroberfläche und setzt außerdem das Entwurfsmuster MVVM (Model View Viewmodel) konsequent um. Da dieser Beitrag aber vor allem für Personen gedacht ist, die das erste Mal mit der Entwicklung von Benutzeroberflächen zu tun haben, wäre dies zu komplex, wird aber in einem zukünftigen Beitrag behandelt. Wenn du jetzt schon mehr zu WPF wissen möchtest empfehle ich dir folgendes Fachbuch, dass ich auch selbst gelesen habe: Windows Presentation Foundation 4. Einführung und Praxis

Windows Forms Projekt erstellen

Als erstes muss ein neues Projekt vom Typ Windows Forms-Anwendung angelegt werden:

Quelle: Eigene Darstellung

Dann erstellt eure Entwicklungsumgebung, in meinem Fall Visual Studio, für euch das Projekt mit verschiedenen Dateien.

Aufbau einer Windows Forms Anwendung

In Visual Studio findet ihr im Projektmappenexplorer (im Standard auf der rechten Seite von Visual Studio zu finden, ansonsten über „Ansicht“ -> „Projektmappenexplorer“ oder [STRG] + [ALT] + [L] aufrufbar) eine Form1.cs, eine Form1.Designer.cs, in meinem Fall noch eine Form1.resx und eine Program.cs Datei.

Quelle: Eigene Darstellung

 

Datei Erklärung
Form1.cs Die Form1 Klasse ist gesplittet in Designerdatei und Form1.cs. Die Form1 Datei enthält Code der ausgeführt wird, wenn der Benutzer Interaktionen mit der Benutzeroberfläche stattfinden lässt, also zum Beispiel einen Button drückt, die Maus bewegt, eine Taste auf der Tastatur drückt usw. Außerdem kann man in die vordefinierte eventgesteuerte Methode „Form1_Load“ Quellcode schreiben, der unmittelbar vor der Anzeige des Formulars, ausgeführt wird. Aus dieser Datei heraus wird bei der Erstellung der Form1 Klasse (um genau zu sein beim Aufruf des Form1 Konstrukturs), die Methode InitializeComponent() aus der „Form1.Designer.cs“ aufgerufen.
Form1.Designer.cs In der Designerdatei werden, in der Regel, die Steuerelemente (Controls) des Formulars deklariert, initialisiert, positioniert, Attribute gesetzt und formatiert.
Form1.resx Diese Datei habe ich manuell hinzugefügt, sie wird genutzt um Ressourcen geordnet abzulegen. Das können zum Beispiel Stringressourcen sein, also irgendwelche Zeichenfolgen (oft Wörter und Texte). Das macht Sinn damit man diese geordnet an einer Stelle ablegen kann und bei Änderungen, oder Hinzufügen einer neuen Sprache, nur an einer Stelle und nicht an 100 Stellen angepackt werden muss. Es können aber auch, wie in diesem Fall, Bilder oder Symbole, Audiodateien und weitere Ressourcentypen abgelegt werden.
Program.cs In dieser Klasse findest du den Haupteinstiegspunkt der Anwendung. Von hier aus wird das Formular Form1 erzeugt und ausgeführt.

Quelle: Eigene Darstellung

Ausführen der Anwendung

Wenn du [F5] drückst, oder über das Menü „Debuggen“ -> „Debugging Starten“ navigierst, kannst du deine Anwendung debuggen, also Starten mit zusätzlicher Option den Code zu untersuchen, während das Programm läuft. Bei einer neuen Anwendung sieht das Ganze noch recht unspektakulär aus, eine leeres Fenster wird angezeigt.

Quelle: Eigene Darstellung

Der Entwurfsmodus

Wenn du auf die Form1.cs Datei doppelt klickst, wird dir das Formular im Entwurfsmodus angezeigt. Hier bekommst du eine direkte Vorschau darauf, wie das Formular aussieht, außerdem stehen dir noch zusätzliche Optionen wie das Eigenschaftsfenster, eine Übersicht der zur Verfügung stehenden Events und eine Toolbox zur Verfügung. Mit der Toolbox (falls nicht bereits offen, wird diese über das Menü „Ansicht“ -> „Toolbox“ oder [STRG] + [ALT] + [X] geöffnet) können sehr einfach, mit der Maus per „Drag and Drop“, Steuerelemente auf das Formular gezogen werden. Dadurch werden neue Steuerelemente in der Form1.Designer.cs Datei erstellt, das kann man natürlich auch selber machen. Wenn ein Steuerelement den Fokus hat, können außerdem über das Eigenschaftsfenster, Eigenschaften wie zum Beispiel der Name des Steuerelements gesetzt werden.

Die Oberfläche designen

Nachdem wir nun eine leere Windows Forms Anwendung erstellt haben, muss die Oberfläche designt werden, nutze dazu entweder die Toolbox und die Entwurfsansicht, oder schreib direkt Code in die Form1.Designer.cs Klasse. Als Vorlage kannst du die folgende Abbildung, ohne Hintergrundbild, nutzen.

Quelle: Eigene Darstellung

Es sind also 3 Textboxen, 3 Label zu den Textboxen, 4 Radiobuttons, und 4 normale Buttons zu benennen und zu Erstellen.

Das kann zum Beispiel folgendermaßen in der Form1.Designer.cs Datei realisiert werden (am Ende des Beitrags findest du den gesamten Quellcode zum kostenlosen Download):

namespace WindowsFormsApplication1
{
partial class Form1
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Vom Windows Form-Designer generierter Code

/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.textBox_Ergebnis = new System.Windows.Forms.TextBox();
this.bt_berechnen = new System.Windows.Forms.Button();
this.bt_Wurzel = new System.Windows.Forms.Button();
this.bt_Reset = new System.Windows.Forms.Button();
this.bt_Beenden = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.Zahl2 = new System.Windows.Forms.Label();
this.radioButtonAddieren = new System.Windows.Forms.RadioButton();
this.radioButtonSubtrahieren = new System.Windows.Forms.RadioButton();
this.radioButtonMulti = new System.Windows.Forms.RadioButton();
this.radioButtonDividieren = new System.Windows.Forms.RadioButton();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(73, 86);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(109, 20);
this.textBox1.TabIndex = 4;

//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(233, 86);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(110, 20);
this.textBox2.TabIndex = 5;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 17.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.Location = new System.Drawing.Point(75, 56);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(72, 29);
this.label1.TabIndex = 6;
this.label1.Text = "Zahl1";
//
// textBox_Ergebnis
//
this.textBox_Ergebnis.Location = new System.Drawing.Point(77, 169);
this.textBox_Ergebnis.Name = "textBox_Ergebnis";
this.textBox_Ergebnis.Size = new System.Drawing.Size(105, 20);
this.textBox_Ergebnis.TabIndex = 8;
//
// bt_berechnen
//
this.bt_berechnen.Location = new System.Drawing.Point(583, 79);
this.bt_berechnen.Name = "bt_berechnen";
this.bt_berechnen.Size = new System.Drawing.Size(108, 31);
this.bt_berechnen.TabIndex = 10;
this.bt_berechnen.Text = "Berechnen";
this.bt_berechnen.UseVisualStyleBackColor = true;
this.bt_berechnen.Click += new System.EventHandler(this.bt_berechnen_Click);
//
// bt_Wurzel
//
this.bt_Wurzel.Location = new System.Drawing.Point(583, 144);
this.bt_Wurzel.Name = "bt_Wurzel";
this.bt_Wurzel.Size = new System.Drawing.Size(108, 31);
this.bt_Wurzel.TabIndex = 11;
this.bt_Wurzel.Text = "Wurzel aus Summe";
this.bt_Wurzel.UseVisualStyleBackColor = true;
this.bt_Wurzel.Click += new System.EventHandler(this.button2_Click);
//
// bt_Reset
//
this.bt_Reset.Location = new System.Drawing.Point(583, 215);
this.bt_Reset.Name = "bt_Reset";
this.bt_Reset.Size = new System.Drawing.Size(108, 31);
this.bt_Reset.TabIndex = 12;
this.bt_Reset.Text = "Reset";
this.bt_Reset.UseVisualStyleBackColor = true;
this.bt_Reset.Click += new System.EventHandler(this.bt_Reset_Click);
//
// bt_Beenden
//
this.bt_Beenden.Location = new System.Drawing.Point(583, 283);
this.bt_Beenden.Name = "bt_Beenden";
this.bt_Beenden.Size = new System.Drawing.Size(108, 31);
this.bt_Beenden.TabIndex = 13;
this.bt_Beenden.Text = "Beenden";
this.bt_Beenden.UseVisualStyleBackColor = true;
this.bt_Beenden.Click += new System.EventHandler(this.bt_Beenden_Click);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 17.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label4.Location = new System.Drawing.Point(72, 136);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(110, 29);
this.label4.TabIndex = 14;
this.label4.Text = "Ergebnis";
//
// Zahl2
//
this.Zahl2.AutoSize = true;
this.Zahl2.Font = new System.Drawing.Font("Microsoft Sans Serif", 17.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Zahl2.Location = new System.Drawing.Point(228, 54);
this.Zahl2.Name = "Zahl2";
this.Zahl2.Size = new System.Drawing.Size(72, 29);
this.Zahl2.TabIndex = 15;
this.Zahl2.Text = "Zahl2";
//
// radioButtonAddieren
//
this.radioButtonAddieren.AutoSize = true;
this.radioButtonAddieren.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.radioButtonAddieren.Location = new System.Drawing.Point(403, 111);
this.radioButtonAddieren.Name = "radioButtonAddieren";
this.radioButtonAddieren.Size = new System.Drawing.Size(89, 20);
this.radioButtonAddieren.TabIndex = 16;
this.radioButtonAddieren.TabStop = true;
this.radioButtonAddieren.Text = "Addieren";
this.radioButtonAddieren.UseVisualStyleBackColor = true;
//
// radioButtonSubtrahieren
//
this.radioButtonSubtrahieren.AutoSize = true;
this.radioButtonSubtrahieren.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold);
this.radioButtonSubtrahieren.Location = new System.Drawing.Point(403, 158);
this.radioButtonSubtrahieren.Name = "radioButtonSubtrahieren";
this.radioButtonSubtrahieren.Size = new System.Drawing.Size(114, 20);
this.radioButtonSubtrahieren.TabIndex = 17;
this.radioButtonSubtrahieren.TabStop = true;
this.radioButtonSubtrahieren.Text = "Subtrahieren";
this.radioButtonSubtrahieren.UseVisualStyleBackColor = true;
//
// radioButtonMulti
//
this.radioButtonMulti.AutoSize = true;
this.radioButtonMulti.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold);
this.radioButtonMulti.Location = new System.Drawing.Point(403, 205);
this.radioButtonMulti.Name = "radioButtonMulti";
this.radioButtonMulti.Size = new System.Drawing.Size(117, 20);
this.radioButtonMulti.TabIndex = 18;
this.radioButtonMulti.TabStop = true;
this.radioButtonMulti.Text = "Multiplizieren";
this.radioButtonMulti.UseVisualStyleBackColor = true;
//
// radioButtonDividieren
//
this.radioButtonDividieren.AutoSize = true;
this.radioButtonDividieren.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold);
this.radioButtonDividieren.Location = new System.Drawing.Point(402, 256);
this.radioButtonDividieren.Name = "radioButtonDividieren";
this.radioButtonDividieren.Size = new System.Drawing.Size(97, 20);
this.radioButtonDividieren.TabIndex = 19;
this.radioButtonDividieren.TabStop = true;
this.radioButtonDividieren.Text = "Dividieren";
this.radioButtonDividieren.UseVisualStyleBackColor = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ControlLightLight;
this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
this.ClientSize = new System.Drawing.Size(730, 403);
this.Controls.Add(this.radioButtonDividieren);
this.Controls.Add(this.radioButtonMulti);
this.Controls.Add(this.radioButtonSubtrahieren);
this.Controls.Add(this.radioButtonAddieren);
this.Controls.Add(this.Zahl2);
this.Controls.Add(this.label4);
this.Controls.Add(this.bt_Beenden);
this.Controls.Add(this.bt_Reset);
this.Controls.Add(this.bt_Wurzel);
this.Controls.Add(this.bt_berechnen);
this.Controls.Add(this.textBox_Ergebnis);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Taschenrechner";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox_Ergebnis;
private System.Windows.Forms.Button bt_berechnen;
private System.Windows.Forms.Button bt_Wurzel;
private System.Windows.Forms.Button bt_Reset;
private System.Windows.Forms.Button bt_Beenden;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label Zahl2;
private System.Windows.Forms.RadioButton radioButtonAddieren;
private System.Windows.Forms.RadioButton radioButtonSubtrahieren;
private System.Windows.Forms.RadioButton radioButtonMulti;
private System.Windows.Forms.RadioButton radioButtonDividieren;
}
}

Jetzt haben wir die Oberfläche designt, die nötige Logik um die Funktion des Taschenrechners abzubilden fehlt aber noch.

Events nutzen

In dieser ersten, einfachen Umsetzung, wird bewusst aus Gründen der Einfachheit, auf das Konzept der Objektorientierung und andere Entwurfsmuster, verzichtet. Wenn man, in der Entwurfsansicht, auf ein Steuerelement, wie zum Beispiel den „Berechnen Button“ einen doppelten Mausklick ausführt, wird für das entsprechende „OnClick-Event“ ein Delegate erstellt, der auf die auszuführende Methode zeigt, wenn das Event ausgeführt wird (in der Datei Form1.Designer.cs).

Beispiel:

this.bt_berechnen.Click += new System.EventHandler(this.bt_berechnen_Click);
  • bt_berechnen ist ein Button, nämlich der „Berechnen Button“
  • Click ist das Event, das Eintritt wenn man mit der Maus auf dieses Element klickt
  • Diesem Event wird ein neues Objekt vom Typ „Delegate“, erzeugt durch den Aufruf EventHandler(<Name der auszuführenden Methode>), welches auf die Methode bt_berechnen_Click verweist, zugewiesen
  • Die Methode bt_berechnen_Click wird ausgeführt, wenn mit der Maus auf den Button bt_berechnen geklickt wird.

Außerdem wird die Methode „bt_berechnen_Click“ automatisch in der Form1.cs Klasse erstellt.

Diesen Vorgang kann man entweder auch automatisch, mit einem Doppelklick auf die anderen Steuerelemente nachziehen, oder besser, weil viel lehrreicher, wäre der Weg dies manuell für die anderen Steuerelemente zu realisieren.

Logik implementieren

Jetzt haben wir eine Benutzeroberfläche, wir wissen wie die Verknüpfung zwischen Buttons, Events, Delegates und der Methode auf die das Delegate zeigt, umgesetzt wird. Es fehlt also noch die eigentliche Funktion des Taschenrechners. Dazu muss in der Methode auf die das Event verweist:

  1. Der aktuelle Wert aus den Textboxen ausgelesen werden (ggf. überprüft werden, ob dieser Wert valide ist, also ob es sich um eine gültige Zahl handelt)
  2. Die Rechenoperation ausgeführt werden und somit das Ergebnis berechnet werden
  3. Das Ergebnis in die Textbox für das Ergebnis geschrieben werden

Machen wir das doch mal an dem Beispiel des „Dividieren“ Operators.

private void bt_berechnen_Click(object sender, EventArgs e)
        {
            zahl1 = Convert.ToDouble(textBox1.Text);
            zahl2 = Convert.ToDouble(textBox2.Text);

            ergebnis = BerechneGrundrechenArten();

            textBox_Ergebnis.Text = Convert.ToString(ergebnis);            
        }

Hier werden zwei zuvor Global deklarierte int-Variablen (zahl1, zahl2) die zum Datentyp double konvertierte Werte, der zugehörigen Textboxen, zugewiesen. Die Anweisung „textBox1.Text“ ruft auf der Textbox die den Namen textBox1 trägt, die Eigenschaft Text auf. Diese Eigenschaft enthält den Text der in der Textbox steht. Mit Text kann man aber nicht rechnen, deshalb muss dieser Wert erst in einen numerischen Datentyp umgewandelt, man sagt „konvertiert“, werden.

Anschließend wir eine neue Methode BerechneGrundrechenArten() ausgeführt, die wiederum das Ergebnis der Rechenoperation zurückgibt. In dieser Methode wird die Eigenschaft „Checked“ der RadioButtons, die die Rechenoperation angeben, abgefragt. Wenn „checked == true“ ist, dann ist dieser RadioButton gesetzt und es wird das Ergebnis entsprechend dieser Operation berechnet. Außerdem wird eine Division durch 0 verhindert.

 

if (zahl2 == 0 && radioButtonDividieren.Checked == true) MessageBox.Show("Division durch Null nicht zulässig", "Fehlermeldung");
            if (radioButtonAddieren.Checked == true) ergebnis += zahl1 + zahl2;
            if (radioButtonSubtrahieren.Checked == true) ergebnis -= zahl1 - zahl2;
            if (radioButtonDividieren.Checked == true) ergebnis /= zahl1 / zahl2;
            if (radioButtonMulti.Checked == true)
            {
                if (ergebnis != 0) ergebnis *= zahl1 * zahl2;
                else ergebnis = zahl1 * zahl2;
            }

            return ergebnis;

Das Ergebnis wird zurückgegeben und der ergebnis Variable aus der bt_berechnen_Click Methode zugewiesen. Anschließend wird das Ergebnis dann in den Datentyp „string“ konvertiert und der Wert wird der Eigenschaft „Text“ der Ergebnistextbox zugewiesen.

Einsatzempfehlung

Windows Forms sollte man nutzen, wenn man eine Client- oder eigenständige Windows Anwendung programmieren möchte, die auch ohne Internetverbindung zurechtkommt und außerdem die Anzahl der Formulare in einem (sehr) niedrigen Bereich angesiedelt ist. Wenn man weiß, dass man viele Formulare, benötigt oder dass die Anwendung komplexer wird, ist es empfehlenswert, sich mit WPF auseinander zu setzen, das von vornherein bidirektionale Datenbindung, so wie das MVVM Pattern unterstützt.

Download des Quellcodes

Wenn man zum erstern Mal mit Benutzeroberflächen zu tun hat, dann mag dieser Beitrag vielleicht nicht ganz trivial erscheinen. Deshalb empfehle ich den Quellcode kostenlos herunterzuladen, auszuprobieren und parallel dazu den Beitrag zu verstehen und sich selbst auszuprobieren.

Einen komplexeren, wissenschaftlichen Taschenrechner, und viele weitere lohnenswerte Applikationen kannst du im Paket User Interface erwerben.

Empfohlene weiterführende Literatur:

C# 6 mit Visual Studio 2015: Das umfassende Handbuch: Spracheinführung, Objektorientierung, Programmiertechniken

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.