User Interfaces (Teil 1)

Veröffentlicht: 23. Mai 2002 | Aktualisiert: 20. Jun 2004

Von Bernd Marquardt

Bedienoberfläche ist das Aushängeschild einer Anwendung. Bei der Programmierung kommt es deshalb auf einfache und flexible Gestaltungsmöglichkeiten an. Die Windows Forms des .NET Framework bieten dem Programmierer genau diese Unterstützung. Der zweiteilige Artikel zeigt, wie Sie schnell ein Fenster mit Menü, Toolbar, Statuszeile und Dialogen ausstatten.

Auf dieser Seite

 Kurzer Exkurs: Die Common Language Runtime (CLR)
 Windows Forms: Alles für das User Interface
 Hello Universe: Initialisieren und darstellen
 Eventverarbeitung mit Delegates
 Anlegen eines neuen Projektes in Visual Studio .NET
 Ein Menü hinzufügen

Die gängige Windows-Programmierung benutzt verschiedene Verfahren, um auf die Funktionen von Microsoft Windows zuzugreifen. In den Anfangstagen von Windows musste man mit Programmiersprachen wie C das API (Application Programming Interface) von Windows ansprechen. Die Programmierung in diesem Umfeld war recht kompliziert und der Lernaufwand war immens hoch. Allein um ein leeres Fenster auf den Bildschirm zu bringen, waren viele Zeilen Code nötig. Dem stand jedoch eine große Flexibilität gegenüber: Über das API konnte der Entwickler alles anprogrammieren und somit anpassen.

Mit dem Microsoft C++-Compiler der Version 7 kam dann die erste MFC (Microsoft Foun-dation Classes). Diese erste Version des momentanen Standards für Windows-Entwicklung in C++ war jedoch nur eine äußerst dünne Hülle um das Windows-API. Erst mit der nächsten Version des Compilers (Microsoft Visual C++ 1.0) wurde die MFC dann richtig erwachsen und in vielen Softwareprojekten eingesetzt. Das Schreiben von Windows-Programmen mit ausgefeilten Benutzerschnittstellen wurde durch die neue Klas-senbibliothek wesentlich einfacher und übersichtlicher. Trotzdem konnte der Programmierer immer noch alle Windows-Features nutzen.

Anfang der 90er Jahre brachte Microsoft die Sprache Visual Basic 1.0 heraus und krem-pelte damit den Markt für die Windows-Programmierung über Nacht um. Visual Basic war schnell und leicht zu erlernen. Der Ansatz, zuerst das User-Interface zu gestalten und dann die Funktionalität dahinter zu hängen, fand schnell seine Anhänger. Mit Visual Basic war es sehr einfach, Windows-Programme zu entwickeln.

Viele Programmierer benutzen seitdem diese Sprache, da sie alle unwesentlichen und selten benutzten Interna der Windows-Programmierung versteckt und die Konzentration auf die Lösung des anstehenden Problems möglich macht. Probleme mit Visual Basic ent-standen jedoch immer dann, wenn ein Programmierer Dinge tun wollte, die nicht in Visual Basic vorgesehen waren.

Alle aufgezeigten Varianten der Windows-Programmierung haben jedoch entscheidende Nachteile: Zunächst laufen sie nur auf einer Plattform. Außerdem sind alle abhängig von einer ganz bestimmten Programmiersprache. Schließlich hatte auch jede der oben genannten Varianten ihre Eigenarten, die man so ganz nebenbei als Programmierer auch noch erlernen musste.

Ideal wäre eigentlich eine einzige, objektorientierte Programmier-Schnittstelle für die Windows-Programmierung. Diese Schnittstelle muss von allen .NET-Programmiersprachen aus benutzbar sein. So kann der Programmierer einmal gewonne-nes Wissen mit unterschiedlichen Sprachen nutzen. Eine solche gemeinsame Schnittstelle bietet nun das .NET Framework mit den Windows-Forms-Klassen. Diese Klassen für das Gestalten von Benutzerschnittstellen können derzeit von C#, VB, C++ (eingeschränkt), J# und JScript verwendet werden.

Kurzer Exkurs: Die Common Language Runtime (CLR)

Das Microsoft .NET Framework basiert auf der Common Language Runtime (CLR), also auf einer einzigen Runtime, die von allen .NET-Sprachen genutzt wird. Zu dieser Runtime gehört die Base Class Library, welche auch die Windows-Forms-Klassen enthält. Beide Elemente - Common Language Runtime und Base Class Library - werden von diversen Sprachen wie Visual Basic, C++, C# oder J# benutzt.

Die Base Class Library ist die angesagte Schnittstelle für den Programmierer, um Applikationen zu schreiben. Sie ist eine sehr reichhaltige Klassenbibliothek.

wft1_1

Ziel der Common Language Runtime ist es, alles - vom Typsystem, Kontext für Transak-tionen bis hin zum Loader für ferne Komponenten - zusammenzufassen. Um das zu er-reichen, hat jede Programmiersprache ihren Compiler, der einheitlichen IL-Code (Intermediate Language) erzeugt. IL-Code ist ein Stack-orientierter Code, der sehr schnell wei-terverarbeitet werden kann. Beim Aufruf der Applikation wird er vom JIT-Compiler in na-tiven Maschinencode übersetzt. (Anmerkung: Allein der Microsoft C++-Compiler kann noch nativen Maschinencode zum Beispiel für X86-Prozessoren erzeugen und unterstützt damit auch alte MFC-Applikationen.) Durch IL-Code und JIT-Compiler wird eine Unab-hängigkeit des Programms von der Hardwareplattform erreicht.

Dank dieses Konzepts werden alle .NET-Sprachen gleichwertig: Alle Compiler erzeugen für bestimmte Sprachkonstrukte einen sehr ähnlichen IL-Code, der wiederum die für alle Sprachen gleiche Runtime verwendet. Die Runtime macht es zudem möglich, dass zum Beispiel eine C#-Klasse von einer VB-.NET- oder einer C++-Klasse abgeleitet werden kann. Aus all diesen Faktoren wiederum resultiert eine einheitliche Fehlerbehandlung in der Runtime sowie eine (nahezu) gleiche Performance. Visual-Basic-Programme erhalten dadurch eine deutliche Performance-Verbesserung.

Neben den vielen Vorteilen durch die Common Language Runtime, muss man natürlich auch die Nachteile sehen: Zum einen müssen wir Programmierer wieder einmal umlernen, und das kostet Zeit und Geld. Des weiteren ist alter Code nicht einfach mit dem .NET Framework weiterverwendbar. Er muss in großen Teilen neu geschrieben werden. Alte COM-Komponenten, ActiveX-Controls und auch normale DLLs können unter .NET weiterverwendet werden. User-Interface-Code, egal ob mit VB oder den MFC entwickelt, muss für Windows Forms unter .NET neu angelegt werden.

 

Windows Forms: Alles für das User Interface

Die .NET-Klassenbibliothek enthält sehr viele Klassen. Aus diesem Grund werden die Klassen in Namensräume (namespaces) unterteilt. Der Wurzel-Namensraum (root namespace) heißt "System". Jedes Programm, das mit der Common Language Runtime laufen soll, wird diesen Namensraum benutzen. Der Namensraum, der uns im Weiteren nun ausschließlich interessiert, ist "System.Windows.Forms". In diesem Namensraum befin-den sich alle Klassen, die für die Programmierung von Rich Client User Interfaces benötigt werden.

Der Namensraum System.Windows.Forms enthält unter anderem:

  • Klassen für Fenster

  • Die Application-Klasse

  • Klassen für die Windows-Controls (Button, Editbox,...)

  • Klassen für Standard-Dialoge (z.B.: Datei öffnen, Drucken,...)

  • Klassen für Menüs

  • Klassen für Images

  • Klassen für das Drucken

  • Klassen für Statuszeile und Toolbar

  • Klassen für das Clipboard (Zwischenablage)

  • Viele Hilfsklassen

Diese Klassen sind, insgesamt gesehen, sehr leistungsfähig. So ist es z.B. ohne Aufwand möglich, eine Grafikdatei (JPG, BMP, TIF, WMF,...) in ein Objekt der Klasse Image zu laden und in einem Fenster darzustellen. Für VB-Programmierer ist das Drucken und das visuelle Editieren von Menüs nun kein Problem mehr.

Ausgangspunkt einer Windows-Forms-Applikation ist eine Instanz der Klasse System.Windows.Forms.Form. Diese Klasse stellt das Hauptfenster der Applikation dar und enthält ähnlich viele Methoden, Eigenschaften (Properties) und Ereignisse (Events), wie die adäquate CWnd-Klasse aus der MFC. Hier einige wichtige Beispiele aus der Form-Klasse:

Properties

Methoden

Events

ClientSize

Activate

Deactivate

FormBorderStyle

Close

Load

Icon

OnClosing

IsMdiChild

OnLoad

MaximizeBox

ShowDialog

MinimizeBox

Menu

ShowInTaskbar

StartPosition

TopMost

WindowsState

Jede Windows-Forms-Applikation stellt sein Hauptfenster über die statische Methode Run der Application-Klasse dar. In der Main-Methode der Applikation wird meistens dieser oder ein ähnlicher Code zu finden sein:

static void Main() { Application.Run(new Form1()); }

Die Form-Klasse heißt hier Form1. Durch den Aufruf der Run-Methode wird der Kon-struktor der Klasse Form1 abgearbeitet, das Fenster wird dargestellt und die Nachrichtenschleife (message loop) wird angelegt.

 

Hello Universe: Initialisieren und darstellen

Die Nachrichten von Forms oder Steuerelementen werden entweder über virtuelle Methoden oder mit Events (Ereignisse) verarbeitet. Im folgenden wird ein Beispiel gezeigt, in welchem die virtuelle Methode OnPaint der Form-Klasse überschrieben wird, um einen Text im Fenster der Applikation auszugeben. Bei diesem Programm handelt es sich um eine erweiterte Version des Hallo-Welt-Programms. Es heißt "Hallo, Universe".

using System; using System.Drawing; using System.Windows.Forms; namespace Hello { public class MyForm : Form { public MyForm() { Text = "Windows Forms Power-Demo"; } protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawString("Hello, Universe!", Font, new SolidBrush(Color.Black), ClientRectangle); } public static void Main(string[] args) { Application.Run(new MyForm()); } } }

Speichern Sie den Code in die Datei Hello.cs und compilieren Sie sie über die folgende Kommandozeile:

csc.exe /target:winexe Hello.cs

Voraussetzung ist, dass Sie das kostenlose .NET SDK installiert haben. Der Parameter "/target:winexe" ist wichtig, da der Compiler standardmäßig ein Kommandozeilen- und kein GUI-Programm erzeugt.

Wir wollen auf den Code noch etwas genauer eingehen. Die Klasse MyForm ist, wie erwartet, von der Form-Klasse abgeleitet. Im Konstruktor von MyForm wird die Eigenschaft Text der Form geändert. Über die Text-Eigenschaft einer Form wird der Text in der Titelzeile eines Fenster eingestellt.

In der Main-Methode wird die Form gestartet, d.h. der Konstruktor wird aufgerufen und die Nachrichtenschleife implementiert. Nun kann das Programm Nachrichten verarbeiten.

In dem Programm werden drei Namensräume benutzt: System, System.Drawing und System.Windows.Forms. Der Drawing-Namensraum wird benutzt, um den Text Hello, Universe! mit der Methode DrawString im Fenster auszugeben. Hierzu wird die Methode OnPaint überschrieben. In die Methode OnPaint wird der Parameter "e" vom Typ PaintEventArgs übergeben. In diesem Parameter stehen spezielle Informationen für die überschriebene Methode oder das gesendete Ereignis. Hier findet man das Graphics-Objekt als Read-Only-Property, mit dem dann schließlich der Text im Fenster ausgegeben wird.

Das Ergebnis sieht dann folgendermaßen aus:

wft1_2

Alle Steuerelemente (Controls) werden durch entsprechende Klassen abgebildet. Die Arbeit mit allen Steuerelementen ist also vollständig objektorientiert. Jedes Steuerelement sendet an sein Elternfenster diverse Ereignisse. Z.B. kann ein Button das Click-Ereignis senden.

 

Eventverarbeitung mit Delegates

Erweitern wir das Hello-Universe-Programm nun so, dass eine Schaltfläche auf der Form erzeugt wird und ein Eventhandler für das Click-Ereignis implementiert wird.

private Button myButton; // Deklaration des Buttons public MyForm() { Text = "Windows Forms Power-Demo"; myButton = new Button(); // Instanz des Buttons myButton.Location = new Point(100, 100); // Position des Buttons myButton.Text = "&Beenden"; // Text des Buttons myButton.Click += new EventHandler(myButton_Click); // Eventhandler Controls.AddRange(new Control[] {myButton}); // Control-Collection } private void myButton_Click(object sender, EventArgs e) { // Schließen des Fensters Close(); }

Nach der Compilation zeigt sich unsere Applikation folgendermaßen:

wft1_3

Sie können auf Beenden klicken, um das Programm zu beenden.

Nach diesem Einstieg in die Programmierung mit Windows Forms möchte ich ein etwas komplexeres Beispiel mit Visual Studio .NET erstellen. In diesem Beispiel sollen ein Menü, ein Toolbar und eine Statuszeile enthalten sein. Außerdem soll die Applikation einen Dialog aufrufen. Doch zu Beginn müssen wir ein neues .NET-Projekt anlegen.

 

Anlegen eines neuen Projektes in Visual Studio .NET

Starten Sie Visual Studio .NET und legen Sie über den Menüpunkt File | New | Project (Datei | Neu | Projekt) ein neues Projekt an. Im dem sich öffnenden Dialog New Project (Neues Projekt) wählen Sie unter Project types (Projekttypen) die Sparte Vi-sual C#-Projects (Visual C#-Projekte) aus, legen auf Basis des Templates Windows Application (Windows Anwendung) ein neues Projekt mit der Bezeichnung myWinApp an und drücken auf die Schaltfläche OK.

Nachdem der Wizard seine Arbeit getan hat, begrüßt Sie der Form-Designer aus Visual Studio .NET mit einem leeren Fenster. Schenken wir der Entwicklungsumgebung an dieser Stelle ein wenig Beachtung, und schauen uns im Solution Explorer (Projektmappen-Explorer) einmal an, was der Wizard alles vorbereitet hat.

wft1_4

Aus der Baumdarstellung können Sie schon entnehmen, dass in einer Solution (Projektmappe) mehrere Projekte enthalten sein können. Unter jedem Projekt finden Sie den Eintrag References (Verweise) und alle weiteren Dateien, die zum Projekt gehören. Unterhalb des Eintrags Verweise können Sie sehen, dass in Erwartung unseres Projektes neben dem Namespace "System", auch noch weitere Namespaces referenziert werden:

System.Data:

Datenbankzugriff über ADO.NET

System.Drawing:

Grafikausgabe (GDI+)

System.Windows.Forms:

Zugriff auf Forms und Controls für Rich Clients

System.XML:

.NET XML Schnittstelle

Namespaces, die nicht benötigt werden, können natürlich aus der Referenzenliste ent-fernt werden.

Darüber hinaus wurden für uns die Klasse Form1, ein Standard-Sinnbild (Icon) für unse-re Applikation und die Datei AssemblyInfo.cs angelegt.

Wir wollen uns nun auf die Klasse Form1 konzentrieren. Schauen wir uns den vom Wizard generierten Sourcecode etwas genauer an. Zu diesem Zweck klicken Sie mit der rechten Maustaste innerhalb des Fensters des Form-Designers und klicken im Kontextmenü den Befehl View Code (Code anzeigen) an.

Im Vergleich zu dem weiter oben beschriebenen Beispiel Hello Universe sind neben den Kommentaren einige wichtige Eintragungen in der Klasse vorgenommen worden. In der Klasse Form1 wird die Deklaration der Variablen components vorgenommen:

private System.ComponentModel.Container components = null;

Diese Variable fungiert als Containerobjekt für Komponenten und hat die Aufgabe, ggf. für bestimmte Komponenten die Dispose-Methode aufzurufen (z.B. bei Imagelist, Timer):

protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); }

Weiterhin wird innerhalb des Konstruktors der Klasse Form1 die Methode Initialize-Component() aufgerufen:

public Form1() { InitializeComponent(); }

Aufzufinden ist diese, nicht gleich sichtbare, Methode unterhalb der Methode Dispose(), und zwar innerhalb des umrandeten Eintrages Windows Form Designer generated Code. Öffnen können Sie diesen Bereich, indem Sie links neben dem Eintrag auf das umrandete Pluszeichen klicken.

Eingerahmt von den Direktiven #region und #endregion steht hier die Methode InitializeComponent(). Innerhalb dieser Methode werden alle instanzierenden und initialisie-renden Arbeiten an den Objekten der Form Form1 vorgenommen.

Beachten Sie bitte bei händischen Änderungen innerhalb der Methode InitializeComponent, dass hier sämtliche Eintragungen vom Form-Designer vorgenommen werden und bei unachtsamen Aktionen evtl. Probleme entstehen könnten.

Stellen Sie nun die Größe des Hauptfensters Ihrer Applikation ein. Dies können Sie ent-weder im Eigenschaften-Fenster durch Änderung der Eigenschaft Size machen oder, und das ist die einfachere Methode, durch Anklicken des Fensters Form1 und Aufziehen auf die gewünschte Größe. Wenn Sie übrigens nun noch einmal in der Methode InitializeComponent() nachschauen, werden Sie feststellen, dass durch die Größenänderung die Zeile mit dem Size-Property entsprechend den neuen Größeneinstellungen angepasst wurde.

An dieser Stelle soll noch darauf hingewiesen werden, dass grundsätzlich jede Einstellung an den Eigenschaften eines Fenster oder Steuerelementes in der Methode Initialize-Component() als Code hinterlegt wird. Es gibt in den Microsoft-.NET-Sprachen keine versteckten Bereiche in den Quellcode-Dateien, in denen z.B. Werte von Eigenschaften abgespeichert werden, wie das bei Visual Basic 6 der Fall ist.

 

Ein Menü hinzufügen

Hinweis: Bei unserer weiteren Programmierung werden wir der Einfachheit halber an vielen Stellen die Standard-Objektnamen benutzen, die von der Visual-Studio-IDE erzeugt werden. In einem "richtigen" Projekt sollten Sie die Objekte unbedingt mit anderen Namen versehen.

Nach diesen Grundlagen werden wir jetzt unserem Fenster ein Menü hinzufügen. Dazu wechseln Sie aus der Ansicht des Sourcecodes wieder in die Ansicht des Form-Designers. Klicken Sie nun unterhalb des Toolbars von Visual Studio .NET auf das Tab Form1.cs [Design] (Form1.cs [Entwurf]).

Öffnen Sie die Toolbox, die sich standardmäßig am linken Bildrand befindet, klicken Sie mit der linken Maustaste im Bereich Windows Forms auf das Steuerelement MainMenu, ziehen Sie dann mit der Maus das Menü auf Ihr Fenster.

Anschließend sollte der Bereich des Form-Designers etwa so aussehen:

wft1_5

Klicken Sie nun mit der linken Maustaste in den blau markierten Bereich Type here (Hier eingeben) des vorbereiteten Menüs. Sie können nun das Menü visuell und interaktiv erstellen.

&Datei (dann Tabulator-Taste drücken) &Bearbeiten (dann Tabulator-Taste drücken) &Ansicht (dann Tabulator-Taste drücken) &Extras (dann Tabulator-Taste drücken) &Fenster (dann Tabulator-Taste drücken)

In unserem Beispiel werden wir folgende so genannte Popup-Menüs erzeugen:

Als Ergänzung wollen wir noch einige Menüeinträge in den Popup-Menüs &Datei und &Ansicht erzeugen. Hierfür klicken Sie mit der linken Maustaste auf &Datei und an-schließend auf darunter liegenden Eintrag Hier eingeben. Machen Sie die folgenden Er-gänzungen im Popup-Menü "Datei":

&Neu

Dann Cursortaste nach unten

-

(dann Cursortaste nach unten)Achtung, ein Minus-Zeichen!

&Beenden

(dann Cursortaste nach unten)

Klicken Sie nun mit der linken Maustaste auf das Popup-Menü &Ansicht und tragen Sie folgende Positionen ein:

&Modal Dialog

(Cursortaste nach unten)

&NonModal Dialog

(dann Cursortaste nach unten)

Fertig!

Innerhalb des Form-Designers ist nun das eingegebene Menü zu sehen:

wft1_6

Sie können das gesamte Menü nun per Mausklick ändern und erweitern. Wenn Sie z.B. die Menüpunkte Modal Dialog und NonModal Dialog vertauschen wollen, so klicken Sie einfach mit der linken Maustaste auf den Eintrag NonModal Dialog, schieben ihn mit Drag & Drop über den Eintrag Modal Dialog und lassen ihn oberhalb fallen.

Um einen neuen Menüpunkt an einer bestimmten Stelle im Popup-Menü zu platzieren, gehen Sie ganz ähnlich vor: Erzeugen Sie den neuen Menüpunkt an der Stelle Hier eingeben. Dann schieben Sie diesen Menüpunkt mit Drag & Drop an die gewünschte Stelle.

Dem Menübefehl Beenden im Popup-Menü Datei wollen wir nun noch Leben einhau-chen. Dabei erfahren Sie, wie ein Menüpunkt mit dem Code verbunden wird, der beim Anklicken ausgeführt werden soll. Der Aufruf der gewünschten Methode wird über ein Event realisiert.

Die meiste Arbeit nimmt uns hierbei jedoch die IDE von Visual Studio .NET ab. Klappen Sie also nun durch Anklicken das Popup-Menü Datei auf und führen Sie einen Doppelklick auf den Menüpunkt Beenden aus. Visual Studio öffnet jetzt die Codeansicht und zeigt Ihnen eine neue Methode in der Form1-Klasse an:

private void menuItem8_Click(object sender, System.EventArgs e) { }

Außerdem hat ein Wizard in der Methode InitializeComponent() für diesen Menüpunkt einen Eventhandler eingetragen:

// // menuItem8 // this.menuItem8.Index = 2; this.menuItem8.Text = "&Beenden"; this.menuItem8.Click += new System.EventHandler(this.menuItem8_Click);

Dieser Eventhandler sorgt dafür, dass im Falle des Anklickens des Menübefehls Beenden der Programmablauf in der Methode menuItem8_Click fortgeführt wird. In dieser Methode implementieren wir nun die Beendigung unseres Programms. Fügen Sie nun folgenden Code in den Handler ein:

private void menuItem8_Click(object sender, System.EventArgs e){ this.Close(); }

Übersetzen und starten Sie nun das Programm und schauen sich das Ergebnis unserer Arbeit an.

Nachdem wir nun ein Menü erzeut haben, wollen wir uns den generierten Sourcecode etwas näher ansehen. Wechseln Sie hierfür wieder in die Code-Ansicht von Form1. Im De-klarationsteil der Klasse Form1 hat VS .NET eine Reihe von Objektvariablen vom Typ MenuItem deklariert. In der Methode InitializeComponent können Sie sehen, wie die-se Objekte instanziert und initialisiert werden.

Das Menü ist hierarchisch in Objektvariablen abgelegt. Es beginnt mit einem Objekt vom Typ MainMenu. Dieses Objekt kennt nun alle Popup-Menüs ("Datei", "Bearbeiten", usw.), die vom Typ MenuItem sind. Jeder MenuItem kann nun selbst wiederum ein weiteres Popup-Menü sein oder nur normale Menübefehle enthalten. Das Popup-Menü Datei in unserem Beispiel enthält als MenuItem die Befehle Neu und Beenden.

Im Form-Designer können Sie durch Auswahl eines beliebigen Menüeintrags Ihres Menüs weitere Eigenschaften im Fenster Properties (Eigenschaften) setzen. Alle Eigenschaften hier zu besprechen, würde den Rahmen dieses Artikels sprengen. Ich möchte an die-ser Stelle als Beispiel nur das Property Shortcut setzen, um dem Menüpunkt ein Tastenkürzel zuzuordnen.

Wählen Sie hierzu den gewünschten Menüpunkt in Ihrem Menü durch Anklicken mit der linken Maustaste aus. Klicken Sie mit der linken Maustaste in das Feld rechts neben Shortcut im Eigenschaften -Fenster der Visual-Studio-IDE. In diesem Feld sollte im Mo-ment None (Keine) stehen (siehe auch nächste Abbildung). Klappen Sie jetzt das Kombinationsfeld auf und wählen Sie das gewünschte Tastenkürzel aus (zum Beispiel [Ctrl][X]).

Übersetzen und starten Sie das Programm und testen Sie den geänderten Menüpunkt.

wft1_7

Neben den Möglichkeiten zur visuellen Bearbeitung von Menüs, können Sie mit ein wenig Programmierung auch mehrere Menüs verwenden, diese sehr einfach nachladen, austauschen oder mischen (mergen). Darüber hinaus können Sie genauso wie Menüs, auch Kontextmenüs erzeugen. Dazu verwenden Sie das Steuerelement ContextMenu aus der Toolbox.