Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 11 Windows-Anwendungen erstellen
Pfeil 11.1 Entwicklungsumgebung
Pfeil 11.2 Eine erste Windows-Anwendung
Pfeil 11.3 Das Codegerüst einer Windows-Anwendung
Pfeil 11.3.1 Einstellungen
Pfeil 11.3.2 Automatisch generierter Startcode
Pfeil 11.3.3 Nachrichtenschleife
Pfeil 11.3.4 Dateien *.vb und *.Designer.vb
Pfeil 11.4 Ereignisse grafischer Windows-Komponenten
Pfeil 11.4.1 Syntax und Nomenklatur
Pfeil 11.4.2 Ereignisse mit Ereignisdaten
Pfeil 11.4.3 Ereignisbehandlung in Visual Studio
Pfeil 11.4.4 Ereignisbehandlung mit OnEreignis-Methoden
Pfeil 11.5 Die Basisklassen einer Form
Pfeil 11.5.1 Control
Pfeil 11.5.2 ScrollableControl
Pfeil 11.5.3 ContainerControl
Pfeil 11.6 Eigenschaften einer Form
Pfeil 11.6.1 Rahmendarstellung
Pfeil 11.6.2 Formspezifisches Symbol
Pfeil 11.6.3 Schaltflächen der Titelleiste
Pfeil 11.6.4 Transparenz
Pfeil 11.6.5 Immer obenauf
Pfeil 11.6.6 Mauszeiger verändern
Pfeil 11.6.7 Farbe (Color)
Pfeil 11.6.8 Schriftart (Font)
Pfeil 11.6.9 Abmessungen einer Form
Pfeil 11.6.10 Position eines Fensters
Pfeil 11.6.11 Anzeigezustand eines Fensters
Pfeil 11.6.12 Arbeitsfläche des Fensters (Clientbereich)
Pfeil 11.6.13 Fokussierreihenfolge
Pfeil 11.6.14 Standardschaltflächen eines Fensters
Pfeil 11.6.15 Unterelemente (ControlsCollection)
Pfeil 11.6.16 Eigenschaften des Form-Objekts
Pfeil 11.7 Ereignisse einer Form
Pfeil 11.7.1 Erzeugen eines Fensters
Pfeil 11.7.2 Größenänderung einer Form
Pfeil 11.7.3 Schließen eines Fensters
Pfeil 11.8 Anwendungen mit mehreren Fenstern
Pfeil 11.8.1 Neue Formulare hinzufügen
Pfeil 11.8.2 Lebenszyklus von Formularen
Pfeil 11.8.3 Mehrere Fenster verwalten
Pfeil 11.8.4 Begrüßungsfenster (Splash)
Pfeil 11.9 Modale Dialogfenster
Pfeil 11.9.1 Layout eines Dialogfensters
Pfeil 11.9.2 Rückgabewert
Pfeil 11.9.3 Eine Form modal öffnen
Pfeil 11.10 Meldungsfenster mit MessageBox
Pfeil 11.10.1 Anzeige mit Show
Pfeil 11.10.2 Rückgabewert der Meldungsfenster
Pfeil 11.11 Die Klasse Application
Pfeil 11.11.1 Die Datei AssemblyInfo.vb
Pfeil 11.11.2 Wartende Ereignisse abrufen (DoEvents)
Pfeil 11.11.3 Eigenschaften und Methoden


Galileo Computing - Zum Seitenanfang

11.8 Anwendungen mit mehreren Fenstern Zur nächsten ÜberschriftZur vorigen Überschrift


Galileo Computing - Zum Seitenanfang

11.8.1 Neue Formulare hinzufügen Zur nächsten ÜberschriftZur vorigen Überschrift

Sie haben zwei Möglichkeiten, um zu Ihrer Anwendung weitere Formulare hinzuzufügen:

  • Sie markieren im Projektmappen-Explorer den Projekteintrag, öffnen das Kontextmenü und wählen HinzufügenWindows Form... Im geöffneten Dialog brauchen Sie nur noch der neuen Quellcodedatei einen passenden Namen zu geben. Dieser ist gleichzeitig auch der Bezeichner der neuen Form-Klasse.
  • Sie leiten von einer vorhandenen Form eine neue ab und ergänzen die abgeleitete um die gewünschten Fähigkeiten.

Leiten Sie eine neue Form von einer existierenden ab, darf die Basisklassenform Komponente des aktuellen Projekts sein. Sie kann aber auch aus einer externen Klassenbibliothek bezogen werden. In jedem Fall sollten Sie aber sicherstellen, dass das Projekt, in dem sich die Basisklassenform befindet, vor dem Ableiten kompiliert wird.

Auch für das Ableiten einer Form haben Sie die Entscheidungsfreiheit: Entweder Sie leiten ab, indem Sie in üblicher Weise die Basisklasse angeben, oder Sie benutzen dazu einen Assistenten. Beide Arbeitsweisen werde ich Ihnen nachfolgend beschreiben.

Alle Steuerelemente, die Sie aus der Toolbox auf die Form gezogen haben, die als Basis dient, sind per Vorgabe als Friend deklariert. Damit haben alle Klassen derselben Applikation Zugriff, und die Steuerelemente können von der Subform aus geändert werden.

Beerben einer Form

In jedem Fall sollten Sie beim Ableiten für die abgeleitete Form eine neue Quellcodedatei bereitstellen. Der Designer kann nämlich je Quellcodedatei nur eine Form anzeigen – und auf die bequeme Arbeit mit dem Designer wollen Sie sicher nicht verzichten. Nachdem Sie die neue Quellcodedatei hinzugefügt haben, leiten Sie die bereitgestellte Klasse einfach von der Basisform ab, zum Beispiel:

Class SubForm : Inherits BaseForm ...

Das Visual Studio 2008 ist pfiffig genug, um zu erkennen, dass Sie im Designer die abgeleitete Form anzeigen lassen wollen. Sie brauchen dazu nur in der Symbolleiste des Solution Explorers in den Designermodus umzuschalten. Alle Eigenschaften und Methoden, die in diesem in BaseForm codiert sind, vererben sich an den Typ SubForm weiter. Sie können Subform anschließend nach Belieben ergänzen und erweitern, sodass sie Ihren Vorstellungen entspricht.

Ableiten mit Visual Studio

Wenn Sie im Dialog zum Hinzufügen einer Komponente zum aktuellen Projekt das Element Geerbtes Formular auswählen, wird der Dialog Vererbungsauswahl angezeigt, in dem alle Formulare des aktuellen Projekts aufgelistet sind. In Abbildung 11.8 sind es die Klassen Form1, Form2 und Form3.

Abbildung 11.8 Der Dialog »Vererbungsauswahl«

Befindet sich die Formschablone in einer anderen Assembly, navigieren Sie über die Schaltfläche Durchsuchen zu der DLL, die die Basisform bereitstellen soll.


Galileo Computing - Zum Seitenanfang

11.8.2 Lebenszyklus von Formularen Zur nächsten ÜberschriftZur vorigen Überschrift

Um zur Laufzeit eine weitere Form anzuzeigen, muss zuerst die Klasse instanziiert werden:

Dim frm As New MyForm()

Damit befindet sich das Formular zwar im Hauptspeicher, auf dem Bildschirm erscheint es aber noch nicht. Die Komponenten der Form sind zu diesem Zeitpunkt allerdings bereits initialisiert. Zur Anzeige muss noch die Methode Show der Form aufgerufen werden:

frm.Show()

Das Gegenstück zu Show ist Hide. Nach dem Aufruf dieser Methode ist die Form zwar nicht mehr sichtbar, bleibt aber weiter im Hauptspeicher und kann ohne Neuinstanziierung mit Show erneut angezeigt werden.

frm.Hide()

Dasselbe Ergebnis erreichen Sie auch durch das Setzen der Eigenschaft Visible der Form auf True bzw. False.

Zum Schließen und Entladen einer Form dient die Methode Close:

frm.Close()

Alle drei Methodenaufrufe haben das Auslösen einer Ereigniskette zur Folge, wie sie weiter oben beschrieben ist.


Galileo Computing - Zum Seitenanfang

11.8.3 Mehrere Fenster verwalten Zur nächsten ÜberschriftZur vorigen Überschrift

Hat eine Anwendung mehrere gleichberechtigte Fenster, müssen Sie ein paar Vorkehrungen treffen, damit die Anwendung nicht früher als erwartet beendet wird.

Nachrichtenschleife

Wir müssen uns noch einmal ansehen, wie wir die Laufzeit einer Windows-Anwendung starten (minimalistische benutzerdefinierte Version):

Shared Sub Main() 
  Application.Run(New HauptFormular()) 
End Sub

Run richtet eine Nachrichtenschleife für das Fenster (Startfenster) ein, dessen Referenz übergeben wird (der automatisch generierte Code erreicht dasselbe über einen Umweg). Die Nachrichtenschleife wird geschlossen, wenn die als Argument übergebene Form entladen wird, denn ein Automatismus fügt dem FormClosed-Ereignis der Form implizit einen Ereignishandler hinzu, der seinerseits Application.ExitThread aufruft. Mit ExitThread wird der aktuelle Thread beendet und damit auch die Laufzeit der Anwendung.

Dieses Verhalten hat weitreichende Konsequenzen. Wird nämlich zur Laufzeit einer Anwendung ein weiteres Fenster mit

Dim frm As New Form2() 
frm.Show()

instanziiert und angezeigt, gliedert es sich in die laufende Nachrichtenschleife ein und teilt sich diese mit dem Startfenster. Das bedeutet aber nicht, dass das neue Fenster gleichberechtigt ist. Vielmehr hat nur das Hauptfenster die Verantwortung darüber, wann die Nachrichtenschleife geschlossen wird – nämlich genau dann, wenn es selbst geschlossen wird. Die Folge ist, dass jedes Fenster der Anwendung geschlossen wird, das zu dieser Nachrichtenschleife gehört.

Dieses Verhalten ist nicht immer wünschenswert. Wenn Sie auf den Automatismus der Nachrichtenschleife verzichten wollen, müssen Sie deren Steuerung selbst in die Hand nehmen. Dabei genügt es nicht, zuerst das Startformular zu instanziieren und danach mit der Methode Run eine Nachrichtenschleife einzurichten:

Dim frm As New StartFormular() 
frm.Show() 
Application.Run()

Bei dieser Lösung sind die Nachrichtenschleife und das Startfenster nicht aneinander gekoppelt, es fehlt definitiv eine Anweisung, um die Nachrichtenschleife zu beenden. Die Anwendung läuft auch nach dem Schließen des letzten Fensters unbemerkt im Hintergrund weiter. Das können Sie sehr schön nach dem Start der Anwendung aus der Entwicklungsumgebung heraus erkennen: Das Visual Studio schaltet nicht in den Entwicklungsmodus zurück.

Die Lösung des Problems ist an sich trivial, denn die Nachrichtenschleife muss genau dann mit Application.Exit bzw. Application.ExitThread beendet werden, wenn das letzte Fenster geschlossen wird. Es stellt sich damit die Frage: Wie können wir feststellen, wann das letzte Fenster geschlossen wird?

Verwaltung der Formulare

Jede Anwendung speichert automatisch alle geöffneten Formulare in der mit Shared an die Klasse Application gebundenen Eigenschaft OpenForms vom Typ FormCollection. Alle Methoden zum Verändern der Liste, wie zum Beispiel Add und Remove, sind nicht öffentlich. Die Liste wird also vollständig vom .NET Framework verwaltet. Ihre Programme können nur lesend darauf zugreifen.

Die Auflistung stellt Ihnen nur drei Funktionalitäten öffentlich zur Verfügung: einen Iterator zum Durchlaufen der Auflistung zum Beispiel in einer For Each-Schleife, die schreibgeschützte Anzahl der Elemente in der Eigenschaft Count und einen schreibgeschützten Indexer. Mehr brauchen Sie nicht, um festzustellen, wann das letzte Fenster geschlossen wird und die Anwendung beendet werden soll. Zur Erinnerung: Wir hatten die feste Bindung zwischen dem Startfenster und der Nachrichtenschleife durch einen Aufruf der parameterlosen Überladung von Application.Run() aufgehoben und mussten nur noch einen Mechanismus finden, um nach dem Schließen der letzten Form auch die Nachrichtenschleife zu beenden.

Ich möchte Sie noch auf eine kleine Stolperfalle aufmerksam machen. Dem Indexer der Auflistung FormCollection können Sie entweder einen Integer oder einen String übergeben. Der Integer beschreibt die Position in der nullbasierten Auflistung. Meistens werden Sie damit jedoch nicht viel Erfolg haben, weil Sie in der Regel die Position des Fensters in der Liste nicht kennen. Besser hingegen ist die Übergabe einer Zeichenfolge. Diese beschreibt den Namen der gesuchten Form.


Hinweis
Wenn Sie ein Formular in OpenForms über den Namen ansprechen, sollten Sie unbedingt für eindeutige Namen sorgen. Eindeutige Titelleistentexte helfen hier nicht weiter.


Mehrfensteranwendung

Schauen wir uns zuerst einmal das Aussehen der Anwendung an, bevor wir Details der Implementierung besprechen. Abbildung 11.9 zeigt den Zustand nach zweimaligem Öffnen eines Fensters mit dem Öffnen-Button.

Abbildung 11.9 Mehrfensteranwendung

Mit der Liste OpenForms ist die Implementation nun sehr einfach. Sie wird im folgenden Listing gezeigt. Im Ereignishandler Zu() von FormClosed prüfen wir, ob mit der aktuellen Form auch die letzte der laufenden Anwendung geschlossen wird. Eine Prüfung im Ereignishandler von FormClosing ist nicht möglich, da zu diesem Zeitpunkt die Auflistung OpenForms noch unverändert ist (das Schließen kann ja noch verweigert werden). Liefert der Zähler Count der Liste den Wert null, sind alle Formulare geschlossen, und die Methode Exit oder ExitThread von Application wird aufgerufen, um (auch) die Nachrichtenschleife zu beenden.

Die Hilfsfunktion Listen() schreibt in alle Textboxen aller geöffneten Fenster, indem sie in einer äußeren For Each-Schleife die Liste OpenForms durchläuft, um die Textboxen aller offenen Formulare anzusprechen. In einer inneren Schleife werden alle in OpenForms gelisteten Formulare nochmals durchlaufen, um den Text der Textbox der Form in der äußeren Schleife zu füllen. Zur Kennzeichnung des aktuellen Formulars in der Liste wird ein Stern verwendet. Zu Demonstrationszwecken wird das Formular über seinen Namen in der Auflistung OpenForms herausgesucht. Der Name ist bewusst anders gewählt als der Titelleistentext.

Sowohl im Ereignishandler Auf() von Shown als auch im Ereignishandler Zu() von FormClosed wird Listen() aufgerufen, um die Auflistungen geöffneter Fenster immer aktuell zu halten. Im Ereignishandler Neu() des Buttons wird ein neues Fenster erzeugt und angezeigt. Der Zähler im Titelleistentext dient nur der leichteren Orientierung.


'...\WinForm\MehrFenster\Fenster.vb

Public Class Fenster

  <STAThread()> Public Shared Sub Main() 
    Dim start As New Fenster() 
    start.Show() 
    start.Name = "Name: " & start.Text 
    Application.Run() 
  End Sub

  Private Shared Sub Listen() 
    For Each fm As Fenster In Application.OpenForms 
      fm.Fensterliste.Text = "" 
      Dim akt As Form = Application.OpenForms(fm.Name) 
      For Each f As Form In Application.OpenForms 
        fm.Fensterliste.Text += f.Text 
        If f.Name.Equals(akt.Name) Then fm.Fensterliste.Text += "*" 
        fm.Fensterliste.Text += Environment.NewLine 
      Next 
    Next 
  End Sub

  Private Shared Zähler As Integer 
  Private Sub Neu(sender As Object, e As EventArgs) Handles Öffnen.Click 
    Dim frm As New Fenster() 
    Zähler += 1 
    frm.Text = "Fenster " & Zähler 
    frm.Name = "Name: " & frm.Text 
    frm.Show() 
  End Sub 
 
  Private Sub Auf(sender As Object, ByVal e As EventArgs) _ 
  Handles MyBase.Shown 
    Listen() 
  End Sub

  Private Sub Zu(sender As Object, e As FormClosedEventArgs) _ 
  Handles MyBase.FormClosed 
    If Application.OpenForms.Count = 0 Then Application.Exit() 
    Listen() 
  End Sub

End Class

Hinweis
Sie sollten in den Projekteinstellungen das Anwendungsframework deaktivieren und Sub Main als Startobjekt festlegen.


Das Programm wird erst beendet, wenn alle Fenster geschlossen wurden. Die Reihenfolge ist beliebig.


Galileo Computing - Zum Seitenanfang

11.8.4 Begrüßungsfenster (Splash) topZur vorigen Überschrift

Manchmal nimmt die Initialisierung einer Anwendung eine längere Zeitspanne in Anspruch. Um den Anwendern zu zeigen, dass das Programm tatsächlich startet, wird während dieser Phase ein sogenanntes Splash-Fenster angezeigt . Splash-Fenster haben keine Titelleiste und reagieren im Allgemeinen nicht auf Ereignisse. Daher ist es nicht notwendig, das Fenster einer Nachrichtenschleife zuzuordnen, und wir können uns in Main eine Instanz der Splash-Form besorgen und anzeigen lassen, bevor die Nachrichtenschleife ins Leben gerufen wird.

Um ein Fenster ohne Titelleiste zu erzeugen, wird FormBorderStyle auf False eingestellt. Die Anzeigeposition ist üblicherweise mittig auf dem Bildschirm, StartPosition ist also FormStartPosition.CenterScreen. Die Gestaltung des Fensters ist beliebig, hier wird ein ganz einfaches verwendet (siehe Abbildung 11.10).

Abbildung 11.10 Einfaches Splash-Fenster

Damit die Initialisierungsarbeiten, die im Beispiel durch eine For-Schleife simuliert werden, nicht beginnen, bevor das Fenster vollständig gezeichnet ist, rufen wir vor der Schleife Application.DoEvents() auf. (Hinweis: Application.DoEvents() nehmen wir weiter unten in diesem Kapitel genauer unter die Lupe.)

In der Praxis können während der Initialisierung Fehler auftreten – beispielsweise wenn mit der Initialisierung ein Datenbank- oder Dateizugriff verbunden ist. Deshalb werden die Initialisierungsarbeiten in einem Try-Block ausgeführt. Tritt eine Ausnahme auf, wird der Anwender benachrichtigt und die Anwendung geschlossen. Um die Fehlerbehandlung zu testen, enthält die Schleife des Beispiels eine Throw-Anweisung, deren Auskommentierung nur aufgehoben werden muss.

Startet die Anwendung fehlerfrei, muss das Splash-Fenster mit Close geschlossen werden. Dann ist auch der Zeitpunkt gekommen, das Hauptfenster der Anwendung mit Application.Run() zu öffnen.


'...\WinForm\MehrFenster\Initialisierung.vb

Public Class Initialisierung

  <STAThread()> Public Shared Sub Main() 
    Dim sp As New Splash() 
    sp.Show() 
    Application.DoEvents() 
    Try 
      For p As Integer = 0 To 100 
        sp.Fortschritt.Text = "Initialisierung " & p & "%" 
        sp.Fortschritt.Refresh() 
        Threading.Thread.Sleep(50) 
        ' Simulation einer Ausnahme 
        ' Throw New Exception("Abbruch") 
      Next 
      sp.Close() 
      Application.Run(New Initialisierung()) 
    Catch 
      MessageBox.Show("Es ist ein Fehler aufgetreten.", _ 
        Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error) 
      Application.Exit() 
    End Try 
  End Sub

End Class

Hinweis
Ein Aufruf von Application.Exit() vor dem Start der Nachrichtenschleife verpufft wirkungslos. Daher darf Application.Run() nicht nach dem Try-Block aufgerufen werden.


Alternativ können Sie das Anwendungsframework in den Projekteinstellungen aktivieren und einen Begrüßungsbildschirm auswählen. Er wird in einem eigenen Thread gestartet und muss über den Aufruf eines Dispose-Delegates geschlossen werden. Aufgrund dieser Problematik habe ich mich hier für eine manuelle Codierung der Main-Methode entschieden.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual Basic 2008
Visual Basic 2008
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Visual Basic 2012






 Visual Basic 2012


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de