Tutorials

Andorra 2D Windowframeworks

Einleitung
Bisher haben wir als Basis unserer Andorra 2D-Anwendung immer die VCL verwendet. Doch zugegebnermaßen bringt uns dies nicht sonderlich viel. Schließlich verwendeten wir die VCL nur zum erzeugen eines Fensters und zum Verknüpfen der Events - das können wir auch ohne VCL und das ohne viel mehr Aufwand. In diesem Tutorial wird Ihnen erklärt, wie die "Andorra 2D Windowframeworks" funktionieren und wie Sie diese effektiv nutzen.

Was ist ein Andorra 2D "Windowframework"?

Allgemeines
Bevor wir über die "Windowframeworks" reden, sollten wir uns erst einmal darüber aufklären, was dieses eigentlich ist.
Abstrakt gesprochen, handelt es sich bei einem Andorra 2D Windowframework um eine Klasse, welche Funktionen zum erstellen eines Fenster bzw. zum Binden an ein bereits bestehendes Fenster zur Verfügung stellt, sowie Ereignisse verwaltet. Durch Verwendung der Andorra 2D Windowframeworks haben sie Zugriff auf eine weitere Abstraktionsebene von Andorra 2D, die es ermöglicht die Fenster- und Ereignisverwaltung komplett unabhängig von einem Fenstersystem durchzuführen.
Die Andorra 2D Windowframework-Klasse besitzt im wesentlichen zwei Methoden:
Als erstes wäre da die "BindTo"-Funktion zu nennen, welche einen beliebigen Pointer auf ein beliebiges, schon existierendes Fenster/eine schon existierende Komponente annimmt. Wir müssen hierbei zwischen zwei Arten von Windowframeworks unterscheiden: Diejenigen, die selbst ein Fenster erstellen und diejenigen, die es ermöglichen auf ein bestehendes Fenster zuzugreifen.

Delphi-Code:
function BindTo(AObj:Pointer):boolean;

Wenn die Anbindung erfolgreich war, kann die "Initialize"-Funktion aufgerufen werden, welches schließlich das Fenster initialisiert. Hier werden außerdem noch die Darstellungseinstellungen übergeben. Aktuell werden diese bei einem Windowframework, welches nicht selbst ein Fenster erstellt, ignoriert.

Delphi-Code:
function InitDisplay(AProps: TAdDisplayProperties): boolean;

Hierbei wird zurückgegeben, ob die Erstellung des Fensters geglückt ist.

Suchen nach Windowframeworks
Bei der praktischen Verwendung der Windowframeworks müssen wir uns um die oben genannten Methoden eigentlich nicht kümmern, da sich die Klasse "TAdDraw" automatisch um deren ansprechen. Und so geht "TAdDraw" vor:

  • Alle eingebundenen Windowframework-Bibliotheken registrieren sich direkt nach dem Programmstart
  • Beim Aufrufen von "TAdDraw.Initialize" geht dieses alle verfügbaren Windowframeworks durch und unternimmt die folgenden Schritte:
    • Ruft die "BindTo" Funktion jedes Windowframeworks mit dem in "TAdDraw.Create" angegebenen "Parent" Parameter auf
    • Gibt die Funktion "true" zurück (hat also Erfolg), so wird die Klassenhirachie der Windowframeworkklasse als String an die ausgewählte Grafikplugin-Bibliothek übergeben
    • Berichtet diese, dass sie mit dem Windowframework kompatibel ist, so wird die Klasse ausgewählt und die Suche erfolgreich abgebrochen
    • Ist kein Windowframework vorhanden, welches die beiden Tests besteht, so kann Andorra 2D nicht initialisiert werden

  • Nun wird von dem ausgewählten Windowframework die "InitDisplay"-Funktion aufgerufen und das Windowframework an die Grafikplugin-Bibliothek übergeben

Die folgende Abbildung illustriert das Suchen nach einem kompatiblem Windowframework noch einmal:

Aus diesem Prozedere ergibt sich für den Benutzer folgende, einfache Verwendungsmöglichkeit der Windowframeworks: Alle Units der Windowframeworks, die verwendet werden sollen, werden einfach in die "uses"-Anweisung in unserem Projekt geschrieben. Durch die automatische Registrierung beim Programmstart, wird unter diesen nach einem Framework gesucht, welches sowohl mit dem Zielfenster als auch dem Plugin kompatibel ist.
Um Kompatibilität zu "alten" Andorra 2D-Anwendungen zu halten, ist standardmäßig eine Windowframeworkunit eingebunden, welche als Target Window ein bestehendes VCL/LCL Fenster annimmt.
Da die Verwendung der VCL/LCL bekanntlich die ausführbare Datei unnötig aufbläht und dies durch die Verwendung entsprechender, neuer, Windowframeworks nicht unbedingt mehr nötig ist, kann das Einbinden des Standardframeworks durch das Definieren eines einfachen Kompilerschalters verhindert werden. Unter Delphi ist dies über "Projekt->Optionen->Verzeichnisse/Bedingungen" möglich. Der Name des Kompilerschalters lautet:

Delphi-Code:
DO_NOT_INCLUDE_STD_WINDOWMGR

Sie müssen das Projekt nach der Definition komplett neu erzeugen (SHIFT+STRG+F9).

Verfügbare Windowframeworks
Nachfolgend eine kurze Auflistung aller Windowframework-Units:

  • AdWin32Window - Wie der Name schon sagt ein Windowframework, welches nur unter Windows (und nur mit Delphi) funktioniert. Es steuert direkt die Windows API an um ein Fenster zu erzeugen.
  • AdGLFWWindow - Ein Windowframework, welches die Bibliothek GLFW verwendet um einen Context samt Fenster zu erzeugen.
  • AdStdWindow - Verwendet die VCL/LCL um ein Fenster zu erzeugen.
  • AdComponentWindow - Ein Windowframework, welches es ermöglicht ein Windowframework direkt auf einer bestehenden Komponente einer VCL/LCL Anwendung zu erstellen. Dieses Framework ist standardmäßig eingebunden. Wie Sie das Einbinden dieser Unit verhindern können, lesen Sie oben nach.

Die letzten beiden Windowframework-Units kümmern sich selbst um das einbinden entsprechender Units, welche an den Verwendeten Compiler bzw. das verwendete Betriebssystem angepasst sind.

Über zwei Klassen
Die Windowframeworks wurden Ursprünglich eingeführt um den Linuxsupport zu ermöglichen.
Unter Windows konnte Andorra 2D der Pluginbibliothek einfach ein Handle auf ein bereits bestehendes Windows-Fenster übergeben. Danach kümmert sich das Plugin selbst um die Erzeugung des entsprechenden Devicecontexts. Unter Linux ist dies jedoch nicht ohne weiteres möglich: Für jedes Fenstersystem müsste eigener Code zur Contexterzeugung mitgebracht werden.
Damit nicht jeder Linuxprogrammierer bei Null starten muss, gibt es eine Reihe von Plattformunabhängigen Bibliotheken, welche sich um das Erzeugen eines Fensters und dem dazugehörigen Context kümmern. Die Frage war, wie man diese Bibliotheken nun so kapseln kann, dass Sie in das Konzept von Andorra 2D passen. Das so entstandene Windowframework-System bietet also:

  • Nach wie vor die Unterstützung von mehreren Grafikplugins
  • Für den einfachen Benutzer keine (oder kaum) sichtbare Änderungen. Andorra 2D soll sich nach dem gleichen Schema wie zuvor verwenden lassen
  • Die Events des erstellten Fensters müssen sich in der Andorra 2D Anwendung verwenden lassen
  • Komplette Trennung des Fenstersystems und dem restlichen Andorra 2D

Wir unterscheiden nun grundlegend zwei Basiswindowframeworkklassen:

  • TAdHandleWindowFramework - Nur unter Windows lauffähig
  • TAdGLContextGeneratingWindowFramework - Nur mit dem OpenGL-Plugin lauffähig

Ein "TAdHandleWindowFramework" besitzt ein Handle, welches von einem beliebigen Grafikplugin (unter Windows) zur Contexterzeugung verwendet werden kann. Das "TAdGLContextGeneratingWindowFramework" erzeugt hingegen in der Hostanwendung schon ein OpenGL-Context, sodass das Grafikplugin nur noch drauf los zeichnen muss.

Unsere VCL/LCL unabhängige Anwendung
In diesem Kaptiel möchten wir nun endlich eine Anwendung erstellen, die die Andorra 2D Windowframeworks ausnutzt und Plattformunabhängig kompilierbar ist. Bitte beachte Sie, dass es sich bei unserem Beispiel nur um einen Vorschlag handelt, den Sie getrost weiter ausbauen können.
Wir erstellen zunächst in der Entwicklungsumgebung ihrer Wahl eine leere Konsolenanwendung, bzw. ein leeres Programm ohne Formulare. Wir fügen eine neue Unit mit dem Namen "Main.pas" zu dem Projekt hinzu. In dieser Deklarieren wir ein neues Objekt namens "TAdAppl":

Delphi-Code:
type
  TAdAppl = class
    public
      procedure Run;
end;

In der Haupanwendungsdatei (also der *.lpr/*.dpr) fügen wir folgenden Code ein:

Delphi-Code:
var
  Appl:TAdAppl;
begin
  Appl := TAdAppl.Create;
  try
    Appl.Run;
  finally
    Appl.Free;
  end;
end.

Nun kommen wir zur Implementierung unserer "TAdAppl.Run"-Methode. Dazu binden wir uns in "Main.pas" die zugehörigen Andorra 2D-Units ein:

Delphi-Code:
uses
  AdClasses, AdEvents, AdTypes, AdDraws, AdStdWindow, AdDLLExplorer;

Wie weiter Oben beschrieben deklarieren wir den Kompilerschalter

Delphi-Code:
DO_NOT_INCLUDE_STD_WINDOWMGR

damit wir später auf die VCL/LCL verzichten können.

Die Implementierung von "Run" sieht nun folgendermaßen aus:

Delphi-Code:
procedure TAdAppl.Run;
var
  AdDLLExplorer: TAdDLLExplorer;
begin
  AdDraw := TAdDraw.Create(nil);
 
  AdDraw.DllName := DefaultPlugin; //Function in the AdDLLExplorer unit

  AdDraw.Display.Width := 800;
  AdDraw.Display.Height := 600;
  AdDraw.Display.BitCount := 32;

  if AdDraw.Initialize then
  begin
    AdDraw.Window.Title := 'Andorra 2D';
    AdDraw.Run;
  end;
  AdDraw.Free;
end;

Anstatt der vielen Kompilerschalter können wir auch die Klasse "TAdDllExplorer" aus der Unit "AdDllExplorer" verwenden, die nach Andorra DLLs in dem Anwendungsverzeichnis sucht.
Ein Druck auf F9 sollte uns (nach der Deklaration der Variable "AdDraw") ein leeres Fenster mit dem Titel "Andorra 2D" beschehren. Nun müssen wir nur noch einige Events verknüpfen, dann sind wir schon am Ziel angelangt.
Nachdem "TAdDraw" ein kompatibles Windowframework gefunden hat, können wir auf dieses über die "Window"-Property zugreifen. Über

Delphi-Code:
AdDraw.Window.Events

erhalten wir auf die Ereignisse des Windowframeworks Zugriff. Wir deklarieren nun eine Methode

Delphi-Code:
procedure Idle(Sender:TObject; var Done:boolean)

in unserer "TAdAppl"-Klasse und verknüpfen diese über

Delphi-Code:
AdDraw.Window.Events.OnIdle := Idle;

mit den Ereignissen. In Idle können wir nun, wie wir es gewohnt sind unseren Andorra 2D-Zeichencode ablegen.
Ab diesem Punkt unterscheidet sich das Programmieren ohne VCL/LCL nicht mehr viel von dem Programmieren damit. Der einzige Unterschied beruht darauf, dass wir die Events "per Hand" verknüpfen müssen.

Indem wir in der "uses" Anweisung "AdStdWindow" durch eine der anderen Windowframeworkunits ersezten, läuft unsere Anwendung beim nächsten Start mit diesem. Wie oben beschrieben, können Sie auch mehrere Windowframeworkunits einbinden. Diese werden in der Reihenfolge ihres Auftretens abgearbeitet. Bindet man also

Delphi-Code:
AdGLFWWindow, AdWin32Window

ein, so wird das GLFW-Framework nur bei der Verwendung eines "OpenGL-Plugins" engesetzt, bei dem DirectX-Plugin hingegen das "AdWin32Window".
Bitte beachten Sie, dass das GLFW-Framework die GLFW-Bibliothek sowie den Pascal-Header dafür benötigt. Beides befindet sich im Prerequisiten-Package von Andorra 2D.

Copyright und Lizenz
(c) by Andreas Stöckel Februar 2008

Der Inhalt dieses Tutorials steht unter der GNU Lizenz für freie Dokumentation.


This page was generated with the help of the following PHP-Scripts: GeSHi a free PHP Syntax highlighter and StringParser_BBCode a free BBCode Parser.