Programmierkurs: Delphi: Erstellung einer grafischen Oberfläche Fortgeschrittene Themen

Aus Wikibooks
Zur Navigation springen Zur Suche springen

Grafiken[Bearbeiten]

Für Grafiken gibt es die Komponente TImage. Man findet sie in dem Register „Zusätzlich“. Doppelklickt man darauf bzw. wählt man die Eigenschaft „Picture“ und klickt auf die drei Punkte daneben, öffnet sich der Bild-Editor. In ihm wird per „Laden ...“ die Grafik in einem Dialog geladen, die erscheinen soll.

An Eigenschaften bietet das Image noch Stretch. Bei Stretch = True bedeutet dies, dass das Bild auf die Größe der TImage-Komponente gezerrt werden soll, ansonsten behält es seine Originalgröße, unabhängig von der Größe des Images.

Die Eigenschaft Proportional = True (neuere Delphi-Versionen) bewirkt, dass das Image beim Strecken das Verhältnis von Höhe und Breite des Originals beibehält.

Bei AutoSize = True erhält die Image-Komponente automatisch die Größe des Originalbildes. Somit werden Stretch und Proportional ignoriert und die Breite und Höhe der Komponente verändert.

Die Eigenschaften Left und Top geben (auch bei anderen Komponenten) die linke obere Position an. Wenn man eine Image-Komponente für Spiele einsetzt, sollte man allerdings die Eigenschaft DoubleBuffered des Formulars auf True stellen (geht nur im Code-Editor im OnCreate-Ereignis). Hiermit wird das Flackern reduziert:

Crystal Clear app terminal.png Code:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.DoubleBuffered := True;
end;

Es wird jedoch im allgemeinen davon abgeraten, eine Image-Komponente als Zeichenfläche für Spiele oder ähnliches zu missbrauchen. Für dynamische Grafiken (also bei Grafiken die sich öfter ändern, wie bei Spielen) sollte man die TPaintbox-Komponente verwenden. Diese eignet sich auch nur bedingt für Spiele, alles was über einfache Dinge wie Tetris hinausreicht, sollte man eher OpenGL verwenden. Dafür gibt es auch einige 2D-Engines die von der Delphi-Community entwickelt wurden. Im deutschsprachigem Raum werden vor allem Fear2D[1] und Andorra 2D[2] benutzt. Für 3D-Spieleprogrammierung ist die DGL-Community[3] besonders zu empfehlen, da diese sehr gute Tutorials zur 3D-Programmierung verfasst hat.

Menüs[Bearbeiten]

Hauptmenüs[Bearbeiten]

Fast alle Anwendungen haben ein Hauptmenü. Dazu wird die Komponente TMainMenu benötigt. Man findet sie in der Komponentenpalette unter Standard. Setzt man sie auf das Formular, so sieht man erstmal nichts außer eine nicht-visuelle Komponente (eine Komponente, die zwar im Erstellungsmodus gekennzeichnet wird, zur Laufzeit jedoch nicht sichtbar ist). Nun klickt man doppelt auf das TMainMenu. Der Menü-Editor öffnet sich. Dort gibt man einem Platzhalter einen Caption. Über Enter bestätigt man die Eingabe. Ein neuer Platzhalter wird erstellt. In erster Ebene verwendet man gewöhnlich nur Menüpunkte wie „Datei“, „Bearbeiten“, ... Diese können Untermenüs enthalten wie z.B. Datei / Neu, Datei / Öffnen. Selektiert man einen Menüpunkt, sieht man darunter einen Platzhalter. Ihm kann genauso ein Caption zugewiesen werden, z.B. "Neues Dokument". Per Enter wird bestätigt und ein neues Item wird erstellt, z.B. „Öffnen“. Das geht endlos weiter. Wenn Sie als Caption „-“ eingeben, wird dies als Trennlinie interpretiert. Einem Buchstaben kann ein „&“ vorangestellt werden, um das Item per Alternativtaste (Alt) aufzurufen. Weiterhin hat jedes Item die Eigenschaft Shortcut. Dort kann ein Tastenkürzel wie z.B. „Strg+S“, „Strg+Alt+V“, „F1“ oder „Strg+Leer“ eingestellt werden. Per Klick wird genauso wie über Betätigung des Shortcuts das OnClick-Ereignis ausgelöst, das wie oben beschrieben definiert werden kann.

Weiterhin kann jedes Item Untermenüs erhalten. Diese können per Kontextmenü / Untermenü erstellen hinzugefügt werden und wieder Untermenüs erhalten.

Kontextmenüs[Bearbeiten]

Für ein Kontextmenü wird die Komponente TPopupMenu verwendet. Sie befindet sich unter Standard neben TMainMenu. Die Vorgehensweise ist dieselbe wie beim MainMenu. Der Komponente, die per Rechtsklick das Kontextmenü aufruft (es können auch mehrere sein), wird bei der Eigenschaft „PopupMenu“ (wenn vorhanden, in neueren Delphi-Versionen rot gekennzeichnet) die PopupMenu-Komponente zugewiesen.

Toolbars[Bearbeiten]

Toolbars bzw. Werkzeugleisten sind ebenfalls in professionellen Anwendungen oft anzutreffen. Man verwendet dazu die Windows-Komponente TToolbar im Register „Win32“. Weiterhin wird eine ImageList benötigt (ebenfalls im Register Win32). Auf diese wird nun doppelt geklickt. Im ImageList-Editor werden per Hinzufügen die benötigten Glyphs (Bitmaps in den Formaten 16x16, 24x24, 32x32, ...) zugewiesen. Diese können per Drag&Drop verschoben werden.

Nun wird der Toolbar-Komponente unter der Eigenschaft „Images“ (rot hervorgehoben) die ImageList zugewiesen. Per Rechtsklick auf die Toolbar kann im Kontextmenü „Neuer Schalter“ oder „Neuer Trenner“ gewählt werden. Bei Schaltern (TToolButton) gibt es die Eigenschaft ImageIndex, die den Index des Glyphs innerhalb der ImageList bestimmt. Erwartet wird eine Ganzzahl. -1 bedeutet: Kein Glyph. Die Nummerierung beginnt bei 0.

Soll der Schalter ein Checker sein, also angeben, ob ein Zustand 1 (true) oder 0 (false) hat, z.B. ob eine andere Toolbar sichtbar ist, wird ihr bei der Eigenschaft „Style“ der Wert „tbsCheck“ zugewiesen. Bei der Eigenschaft Down findet man den Wert False, wenn er nicht gedrückt ist, und True, wenn nicht. Wichtig dazu ist noch der Name des Buttons, den man unter der Eigenschaft „Name“ findet bzw. verändern kann.

Soll der Schalter ein Menü sein, also eine Liste enthalten, die bei Klick „aufpoppt“, stellt man den Wert der Eigenschaft „Style“ auf tbsDropDown. Der Eigenschaft „DropDownMenu“ wird ein PopupMenu zugewiesen, das sich bei einem Klick mit der linken Maustaste auf den Pfeil neben dem Button öffnet.

Ribbon Bar[Bearbeiten]

In den neueren Delphi-Versionen (ab Delphi 2009) gibt es weiterhin die Ribbon Bar-Komponente, um den Programmen ein ähnliches Aussehen wie den neueren Microsoft Office-Anwendungen zu verpassen. Will man diese Komponenten jedoch benutzen, muss man bei Microsoft eine kostenlose Lizenz beantragen und bestimmte Design-Richtlinien beachten. Gedacht ist diese Komponente als einfache und schnelle Alternative zu den Menüs. Hiermit lassen sich Menüleisten und Toolbars als eine Einheit zusammenführen und - bedingt durch die vielen Möglichkeiten - oftmals ganze Einstellungsdialoge hiermit ersetzen.

Statuszeilen[Bearbeiten]

Eine Statuszeile enthält wertvolle Informationen für den Benutzer. Sie befindet sich (meist) im unteren Teil des Formulars. Im einfachsten Fall zeigt sie eine Beschreibung zu einer Schaltfläche an. Diese Beschreibung wird angezeigt, sobald der Benutzer mit der Maus über die Komponente fährt. Sie wird zusätzlich zu dem gelben Hinweis (QuickInfo oder Hint genannt) angezeigt.

Um diesen zu definieren, muss die Eigenschaft „ShowHint“ der jeweiligen Komponente auf True gestellt werden. Die Eigenschaft „Hint“ enthält den Text, der angezeigt wird.

Um eine Statuszeile zu erstellen, zieht man eine TStatusbar (Register Win32) auf das Formular. Die Eigenschaft „AutoHint“ wird ebenso wie die Eigenschaft „SimplePanel“ auf True gestellt. Damit erscheinen nun in der Statuszeile die Hints, die bei der Eigenschaft „Hint“ der Komponente unter der Verwendung von AutoHint = True definiert wurde.

Vorlagen[Bearbeiten]

Für grafische Benutzeroberflächen (GUIs) gibt es drei wesentliche Vorlagen:

  • VCL-Formularanwendung: Anwendung mit einem leeren Formular; wird (bei älteren Delphi-Versionen) standardmäßig erstellt
  • MDI-Anwendung: Multiple Document Interface. Eine Basis, die es möglich macht, mehrere Dokumente zur gleichen Zeit zu verwalten. Beispiele: Photoshop, Phase5. Diese Vorlage erzeugt die Basis eines Texteditors zum gleichzeitigen Bearbeiten mehrerer Dateien.
  • SDI-Anwendung: Single Document Interface. Eine Basis, die grundsätzlich nur ein geöffnetes Dokument unterstützt. Dennoch ist es auch mit SDI möglich, mehrere Dokumente zu verwalten, wenn man die Komponenten dynamisch zur Laufzeit erzeugt. Diese Vorlage erzeugt die Basis für einen Texteditor, mit dem immer nur eine Datei zur Zeit bearbeitet werden kann.

Alle Vorlagen lassen sich über Datei / Neu / Weitere ... verwenden.

MDI-Anwendungen[Bearbeiten]

Eine MDI-Anwendung besteht aus einem Hauptformular (Parent) und mehreren MDI-Kindfenstern (MDI-Children). Im Parent sind Werkzeugleisten (TToolbar oder Zusätze wie Toolbar2000 von Jordan Russell oder TAdvToolbar von TMS Software) und ein Menü (TMainMenu oder gerade genannte Zusätze) untergebracht. Beim Hauptfenster muss die Eigenschaft FormStyle auf fsMDIForm eingestellt sein.

Alle Child-Fenster werden im Formdesigner über Datei / Neu / Formular erstellt, wobei FormStyle auf fsMDIChild gesetzt werden muss. Da Child-Fenster dynamisch erzeugt werden sollten, müssen Sie diese in den Projektoptionen unter Formulare aus der Liste „Automatisch erzeugen“ herausnehmen.

In den Child-Fenstern befindet sich nur eine Editorkomponente für Text, Bilder oder Ähnliches, jedoch keine Menüs oder andere GUI-Komponenten - oder ausschließlich solche. Das Fenster für die direkte Dateibearbeitung sollten Sie von solchen Steuerelementen komplett freihalten und dafür spezielle eigene Fenster anlegen. Nehmen Sie als Beispiel ein Bildbearbeitungsprogramm, das ein Fenster mit den Zeichenwerkzeugen und weitere Fenster enthält. Wenn Sie zum Beispiel eine TMainMenu-Komponente im Child-Fenster platzieren, erhält nicht etwa dieses Fenster das Hauptmenü, sondern das des Hauptfensters wird ersetzt. Das geschieht solange, bis Sie das Child-Fenster schließen oder eines ohne Hauptmenü auswählen.

Die Fenster erhalten in der Titelleiste standardmäßig wie das Hauptfenster Schaltflächen zum Verkleinern, Maximieren und Schließen. Im Maximierten Zustand bekommt das Hauptfenster ein Caption der Form „Hauptfenstertitel - [Kindfenstertitel]“. Damit der verkleinerte Zustand des Fensters wiederhergestellt werden kann, benötigt das Hauptfenster ein Hauptmenü, denn nur dort werden die Titelleistenschaltflächen von maximierten Child-Fenstern angezeigt.

Zu beachten ist, das man beim Schließen des Childfensters das Formular mittels Action := caFree; im OnClose-Ereignis dieses Fensters aus dem Speicher frei gibt.

Tipp: Zum Verwalten der Childfenster bietet sich das dynamisches Array an, welches das Parentfenster automatisch erzeugt. Man kann dann mittels MDIChildren[i] (wobei i den Index des MDI-Childfensters angibt) auf die einzelnen Fenster zugreifen.

SDI-Anwendungen[Bearbeiten]

SDI-Anwendungen sind solche, bei denen immer nur eine Datei im Hauptfenster bearbeitet werden kann, wie zum Beispiel bei Notepad. Solche Anwendungen erstellen Sie über Datei / Neu / VCL-Formularanwendung.

Dialoge[Bearbeiten]

Dialoge sind ebenfalls wichtig. Z.B. der SaveDialog, der OpenDialog, der PrintDialog, der PrinterSetupDialog, der FontDialog oder der ColorDialog. Sie befinden sich im Register Dialoge. Alle diese Dialoge lassen sich mit der Prozedur Execute aufrufen:

Crystal Clear app terminal.png Code:

 OpenDialog1.Execute;

Bei Execute handelt es sich um eine Funktion, die einen Wahrheitswert, also True oder False, zurückgibt. Diesen sollte man auswerten, da True bedeutet, dass der Benutzer auf OK geklickt hat, während er bei False die Dialog mit Abbrechen verlassen hat.

Wie nun die Daten in den einzelnen Dialogen ausgewertet werden, würde hier zu weit führen. Bitte ziehen Sie hierfür Ihre Delphi-Hilfe zurate.

Weiterhin gibt es noch Dialoge mit denen man Benutzerabfragen gestalten kann. Diese sind in der selben Unit wie die Öffnungs- und Speicherndialoge enthalten.

Mit der Funktion MessageDlg erzeugt man Dialoge, die zum Beispiel abfragen können, ob man das Programm wirklich beenden will. Die Funktion benötigt folgende Parameter: den anzuzeigenden Informationstext, die Art des Dialoges (mtNone, mtInformation, mtConfirmation, mtCustom, mtError), die Schaltflächen des Dialogfensters (da kann man entweder eine vorgefertigte Mischung nehmen oder mittels Array selbst die Buttons bestimmen), sowie gegebenenfalls den Hilfeindex (Standard = 0).

MessageDlg gibt auch einen Wert zurück, mit dem man prüfen kann, welchen Button der Benutzer gedrückt hat. Dieser kann mrYes, mrNo und so weiter sein, wie bereits in den Grundlagen beschrieben.

Ein Beispielaufruf könnte so aussehen:

Crystal Clear app terminal.png Code:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if MessageDlg('Wollen Sie beenden?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    Close;
end;

Außerdem gibt es dann noch die sogenannte InputBox. Mit Hilfe dieser kann man Eingaben vom Benutzer einfordern, auch Zahlen und Gleitkommawerte. Für nähere Informationen steht ihnen die Delphi-Hilfe zur Verfügung.

Formatierter Text[Bearbeiten]

Wikipedia hat einen Artikel zum Thema:


Als erste GUI-Anwendung eignet sich ein Texteditor für das Rich Text Format (RTF). Mit ihm ist es möglich, Formatierungen bis hin zu Bildern darzustellen. Auch wenn die Komponente RichEdit (Register Win32) nur formatierten Text ohne Bilder unterstützt, ist es doch eine interessante Komponente, die man kennen sollte.

Öffnen und Speichern[Bearbeiten]

Als erstes zum Laden und Speichern von Dateien - wir brauchen die Methoden LoadFromFile und SaveToFile. Ihnen wird als Parameter der Dateiname übergeben. Zur Dateiauswahl kann man einfach eine OpenDialog-Komponente verwenden:

Crystal Clear app terminal.png Code:

procedure TForm1.LadeDatei;
begin
  try
    if OpenDialog1.Execute then
      RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);  // OpenDialog1.FileName enthält den Namen der ausgewählten Datei
  except
    ShowMessage('Fehler beim Öffnen der Datei');
  end;
end;

Ähnlich ist es beim Speichern:

Crystal Clear app terminal.png Code:

procedure TForm1.SpeichereDatei;
begin
  try
    if SaveDialog1.Execute then
      RichEdit1.Lines.SaveToFile(SaveDialog1.FileName);
  except
    ShowMessage('Fehler beim Speichern der Datei');
  end;
end;

Formatierung[Bearbeiten]

RichEdit-Komponenten bieten vielfältige Möglichkeiten der Textformatierung (rich = engl. für reichaltig). Dies geschieht jedoch nur auf Quelltext-Ebene, da RichEdit selbst keine Steuerelemente hierfür mitbringt. Wenn Sie in einer Anwendung mit RichEdit arbeiten möchten, müssen Sie also selbst z.B. eine Toolbar oder Kontextmenüs anlegen, über die Sie den Text formatieren können.

Schriftfarbe[Bearbeiten]

Der ColorDialog wird aufgerufen und die Schriftfarbe des gewählten Bereichs im RichEdit wird verändert. Das Ganze funktioniert folgendermaßen:

Crystal Clear app terminal.png Code:

procedure TForm1.Button3Click(Sender: TObject);
begin
  if ColorDialog1.Execute then
    RichEdit1.SelAttributes.Color := ColorDialog1.Color;  // selektieren Bereich in der ausgewählten Farbe darstellen
end;

Kompletter Font[Bearbeiten]

Für die komplette Schrift sieht es so aus:

Crystal Clear app terminal.png Code:

procedure TForm1.Button4Click(Sender: TObject);
begin
  if FontDialog1.Execute then
  begin
    RichEdit1.SelAttributes.Color := FontDialog1.Font.Color;  // Farbe
    RichEdit1.SelAttributes.Name := FontDialog1.Font.Name;    // Schriftart
    RichEdit1.SelAttributes.Size := FontDialog1.Font.Size;    // Schriftgröße
    RichEdit1.SelAttributes.Style := FontDialog1.Font.Style;  // Schriftauszeichnung (fett, kursiv, unterstrichen)
  end;
end;

Style kann keinen, einen oder mehrere der folgenden Werte haben: [fsBold] für fett, [fsItalic] für kursiv, [fsUnderline] für unterstrichen und/oder [fsStrikeOut] für durchgestrichen. Style ist ein Set, also eine Menge der vorgenannten Werte. Möchte man einem Stil Werte hinzufügen oder entnehmen, geht das daher folgendermaßen:

Crystal Clear app terminal.png Code:

RichEdit1.SelAttributes.Style := [fsBold];                           // nur fett darstellen
RichEdit1.SelAttributes.Style := RichEdit1.Font.Style + [fsItalic];  // kursiv hinzufügen, Ergebnis: fett, kursiv
RichEdit1.SelAttributes.Style := RichEdit1.Font.Style - [fsBold];    // fett entfernen, Ergebnis: kursiv
RichEdit1.SelAttributes.Style := [];                                 // Standarddarstellung ohne Auszeichnung

Mit RichEdit zu arbeiten, erfordert einiges an Erfahrung. So enthält die Eigenschaft Lines nur den reinen Text ohne jegliche Formatierung. Wenn Sie beispielsweise Text in der gleichen Formatierung an einer Stelle programmatisch einfügen wollen (z.B. bei einer Suchen-Ersetzen-Operation), müssen Sie vorher die Attribute an dieser Stelle auslesen, den neuen Text einfügen, diesen markieren und dann die Attribute darauf anwenden. Alternativ kann man SelStart auf die entsprechende Cursorposition einstellen (vom Beginn des Dokuments an gezählt), SelLength auf 0 setzen und über SelText den einzufügenden Text angeben. Dann wird die Formatierung automatisch übernommen.

Mit etwas Übung werden Sie in RichEdit ein sehr mächtiges Werkzeug für die Textdarstellung und -bearbeitung entdecken.

Internet-Links[Bearbeiten]

  1. Website von Fear2D: http://www.martoks-place.de/delphi/opengl/fear2d
  2. Website von Andorra 2D: http://andorra.sourceforge.net
  3. Website der DGL-Community: http://wiki.delphigl.com/index.php/Hauptseite


Arrow left.png Erstellung einer grafischen Oberfläche Grundlagen Inhaltsverzeichnis Erstellung einer grafischen Oberfläche weitere Themen Arrow right.png