YouTube-Video – Kurztipp: Installation von PostgreSQL auf FreeBSD

Ich dachte mir, ich mache mal ein Video zum Thema: wie installiere ich PostgreSQL auf FreeBSD. Hier ist der Link.

Titelbild PostgreSQL auf FreeBSD installieren
PostgreSQL auf FreeBSD installieren

In dieser Anleitung gehe ich davon aus, dass wir ein frisch installiertes FreeBSD 13 auf dem Rechner haben. Schauen wir uns erst einmal an, welche PostgreSQL-Versionen zur Verfügung stehen:

# pkg search postgresql | grep server

Neben Version 9.6 und 10 bis 13 gibt es bei mir in den Packages die Version 14. Genau diese möchten wir auch installieren:

# pkg install postgresql14-server

Wir bestätigen die Installation des Pakets sowie dessen Abhängigkeiten mit [y] gefolgt von [Enter]. Je nach Internetgeschwindigkeit kann das Herunterladen ein wenig dauern. Bei mir werden, auf einem frischen FreeBSD, 167MB heruntergeladen.

Nach der Installation fügen wir folgende Zeilen in die /etc/rc.conf ein:

postgresql_enable="YES"
postgresql_data="/server/database/postgres"
postgresql_flags="-s"
postgresql_initdb_flags="--encoding=utf-8 --lc-collate=C"

Zeile 1 bedeutet, dass PostgreSQL beim Starten des Betriebssystems automatisch gestartet werden soll und sich auch mit „service“ und „start“ starten lässt (anstelle mit onestart).

Zeile 2 legt fest, wo im Dateisystem die Datenbanken liegen sollen. In meinem Fall lautet der Pfad „/server/database/postgresql“. Den müssen wir aber erst erstellen und ihm die richtigen Rechte zuweisen. Wenn du möchtest, dass deine Daten woanders liegen, musst du den Pfad anpassen:

# mkdir -p /server/database/postgres && chown -R postgres:postgres /server/database/postgres

Zeile 3 beinhaltet einige Flags für den Start von PostgreSQL (-s bedeutet „silent“, es werden nur Fehlermeldungen ausgegeben).

In Zeile 4 wird das Standardencoding auf Unicode 8 gestellt.

Ist das alles erledigt, muss zunächst die Datenbank initialisiert werden:

# service postgresql initdb

Wir möchten jetzt aber von außen z.B. mit unserer eigenen Software oder per pgAdmin4 oder mit anderen Datenbanktools auf die Datenbank zugreifen.

Zuerst müssen wir die Datei „/server/database/postgres/postgresql.conf“ bearbeiten und die Zeile mit „listen_addresses“ auf * setzen (oder auf die IP, auf die PostgreSQL lauschen soll).

Dann müssen wir die Datei „/server/database/postgres/pg_hba.conf“ bearbeiten und unter „IPv4 local connections“ eine Zeile anlegen:

Host all all 192.168.0.0/24 password

Hier liegt allerdings der Hund der Sicherheit begraben. Wir sagen damit, dass alle Hosts in dem Netzwerk 192.168.0.0/24 (ihr müsst eure IP natürlich dementsprechend anpassen) mit allen Benutzern auf alle Datenbanken zugreifen können. Das ist schlecht, deshalb überlegt euch ein vernünftiges Sicherheitskonzept! Darum geht es hier allerdings nicht.

Als nächstes können wir PostgreSQL schon starten:

# service postgresql start

Jetzt legen wir noch einen Benutzer an. Nennen wir ihn „Kalle“ und geben ihm auch als Kennwort „Kalle“. Er soll SuperUser sein und Datenbanken anlegen, aber auch löschen können.

# su – postgres

$ createuser -s -P Kalle

Jetzt könnt ihr euch auf euren PostgreSQL-Server verbinden. Achtet darauf, dass dazu der PostgreSQL-Port (Standard 5432) in eurer Firewall freigeschaltet sein muss.

Hier geht’s zum Video.

Neues YouTube-Video – Qt-Tutorial 004: Installation auf macOS

In diesem neuen Video zeige ich dir, wie du das Qt-Framework auf macOS installieren kannst.

Qt-Tutorial 004: Installation auf macOS
Die Installation auf macOS ist recht einfach. Folge einfach den Schritten in diesem Video.

Ebenso wie unter Windows, ist die Installation auf macOS sehr leicht, letztlich noch einfacher, denn es gibt eine vorgefertigte Paketauswahl.

Man lädt auf https://qt.io einfach das Installationprogramm herunter, mountet die heruntergeladene DMG-Datei und führt das Installationprogramm von Qt aus. Darin meldet man sich mit seinen Login-Daten an und wählt “Qt for desktop development” aus. Dann gönnt man sich einen Tee. Nach kurzer Zeit ist das Programm installiert.

Neues YouTube-Video – Qt-Tutorial 003: Installation auf Windows

Es gibt wieder ein neues Video. Hierin zeige ich, wie du Qt inklusive QtCreator auf Windows installieren kannst.

Qt-Tutorial 003: Installation auf Windows

Um mit Qt zu beginnen, musst du das Framework auf deinem Rechner installieren. Das ist recht einfach und du kannst die Schritte, wie ich sie im Video zeige, einfach nach- oder mitmachen.

Die Installation ist super einfach. Auf https://qt.io lädt man das Installationsprogramm herunter und führt es aus. Dann gibt man seine zuvor erstellten Daten ein, wählte die benötigten Pakete, gönnt sich einen Tee und, je nach Internetgeschwindigkeit, ist Qt dann innerhalb kurzer Zeit installiert.

Portierung eines Delphi-7-Projekts nach FreePascal und Lazarus

Hach, alte Software. Alte, gewachsene Software. Alte, gewachsene, ungepflegte Software. Ja. Wer kennt es nicht? Da gibt es ein Projekt, das hat bestimmt gut fünfundzwanzig Jahre auf dem Buckel und wurde, bis zuletzt, noch mit Delphi 7 “gepflegt”. Von gepflegt kann eigentlich nicht die Rede sein, doch wurden noch minimale Erweiterungen und, allem voran, Verschlimmbesserungen gemacht. Jeglicher Unsinn. Was aber versäumt wurde war, das Projekt, was bei hunderten von Kunden eingesetzt wird, auf eine aktuelle Plattform zu migrieren, damit eine vernünftige und saubere Weiterentwicklung überhaupt noch möglich ist.

Lazarus-IDE

Da komme ich ins Spiel. Problemlöser, Beruhiger … ja, einfach der, der das schlimme Los zog. Ich war zur falschen Zeit am falschen Ort.

Es war so, dass die Weiterentwicklung mit Delphi 7 in der Form nicht mehr möglich war. Die letzte Windowsbetriebssystemversion, auf der Delphi 7 wohl annehmbar lief, war Windows 7, welches ja bereits 2020 abgekündigt war. Ich habe Delphi 7 auf Windows 7 ausprobiert. Es war die Hölle. Stabilität war faktisch nicht vorhanden. Abgesehen von der unsinnigen Weiterentwicklung auf einer uralten, veralteten Plattform mit einem nicht unterstützten Betriebssystem war das Problem, dass Delphi 7 andauernd Fehler warf, stehen blieb, abstürzte. Abgesehen davon gab es in dem Projekt – teils absolut unnötige – Abhängigkeiten, die mitunter zwanzig (20!) Jahre alt waren.

Ich sah drei Möglichkeiten: 1. Ich kündige. Tja, Frau, Kinder und Haus …, also 2. Migration zu Delphi in einer aktuellen Version oder 3., und da war ich mir absolut nicht sicher, wie klug das war, Migration auf eine freie Plattform mittels FreePascal und Lazarus. Der Titel verrät, wofür wir uns entschieden.

Delphi in einer aktuellen Version war meinem Chef nicht nur zu teuer (?!), der Migrationsaufwand aufgrund des alten Codes und der noch schlimmeren Abhängigkeiten, wäre, so dachte ich, mindestens genau so groß gewesen, wie die Migration auf eine andere Plattform. Natürlich bin ich recht naiv an die Sache herangegangen, hatte ich doch wenig Erfahrung mit FreePascal und Lazarus, abgesehen von meinem Spieltrieb, den ich daran ab und zu mal auslebte. Aber was wusste ich? Ich fand, aufgrund meiner Tests, dass die Plattform stabil genug war und ist. Ich spiele gerne mit Technologien und ich habe mir Lazarus und FreePascal über Jahre hinweg angesehen. Die anfänglichen Probleme von vor einer Dekade waren behoben, FreePascal lief eigentlich schon immer ganz gut und Lazarus mauserte sich zu einer stabilen IDE. Ich schlug meinem Chef diese Lösung vor und ich denke, das Hauptargument war “kostenlos”. Ob er den Rest hörte, weiß ich nicht.

Also machte ich mich daran, mich tiefergehend mit FreePascal und Lazarus zu beschäftigen, Blog- und Forenartikel dazu zu lesen und ein oder zwei kleine Testprojekte damit zu schreiben, um das System und die Probleme kennenzulernen. Pascal lag bei mir bereits gut zwanzig Jahre weit weg und ich hatte das nur in zwei kleinen Projekten in meiner alten Firma eingesetzt. Ich kam immer mehr rein.

Dann schnappte ich mir eine virtuelle Maschine, warf ein Windows 7 an, schauderte mich als alter FreeBSD– und Mac-User, installierte Delphi 7 und TortoiseSVN, checkte das alte Projekt aus und installierte alle Abhängigkeiten, die mir die gut zwanzig Jahre alte Doku des Projekts preisgab. Diese elende Abhängigkeitenhölle. Abhängigkeiten, um eine “hübschere” Toolbar hinzukriegen, oder Abhängigkeiten, um eine Pfadauswahl zu implementieren. Die alten Programmierer lebten faktisch die Abhängigkeitshölle und genossen sicher, dass eines Tages ein kleiner Programmierer den Quatsch ausbaden müsse.

Nachdem ich guten Gewissens alle mir bekannten Abhängigkeiten mit teils Windows 3.11-Installationsprogrammen installiert hatte (und hey, dass das Zeug noch lief … man kann von Microsoft ja halten, was man will, aber ich war schon beeindruckt), lud ich das Projekt. Das bedeutet, ich versuchte, es zu laden. Ich weiß nicht, wie die alten Programmierer das zusammengebastelt hatten, aber man musste tatsächlich noch Projekteinstellungen an seine individuelle Entwicklungsumgebung anpassen. Normal? Nein. Stell dir mal vor: du checkst ein Projekt aus, auf irgendeinem Computer, und du musst dann noch die Projektdatei an deine Pfade usw. anpassen, weil dort der Benutzername drin steht. Das geht doch nicht! Und es war einiges und es dauerte noch viel länger, bis ich aufgrund der kargen Doku das Ding mal soweit hatte, dass nicht mehr gemeckert wurde. Ich sage das jetzt mal so: bitte, bitte, bitte, dokumentiert nicht das Offensichtliche (function SchreibeVornamen() // Diese Funktion schreibt den Vornamen…), sondern das, was eben nicht offensichtlich ist. In diesem Projekt wurde, und das mit einer solchen Begeisterung und einem solchen Arbeitsaufwand, nur das Offensichtliche dokumentiert.

Gut, es lud jetzt, es kompilierte. Naja, ab und an. Mal klickte ich auf “Play”, dann kompilierte es, mal auch nicht (ohne Code-Änderung), mal startete es, mal nicht, mal hing es sich auf und dann hing sich ganz Delphi auf. Es war nicht tragbar und wieder einmal wunderte es mich, wie man früher so arbeiten konnte (ich konnte das noch nie).

Nach dem Spruch “Man kann nicht alles haben.” durchwühlte ich den Code. Ich durchwühlte ihn nach den ganzen Abhängigkeiten, die ich ja unter FreePascal und Lazarus nicht mehr zur Verfügung haben sollte. Ich fand viele Stellen, die man einfach nicht brauchte oder für die Lazarus eigene Komponenten mitbrachte. Ich begann, auszuklammern und zu schauen, was noch lief oder was einfach nur sinnlos darin war. Ich fand so einiges. Als ich nach einigen Tagen der Pein dachte, fertig zu sein, dachte ich mir: Jetzt ist der Zeitpunkt da, an dem ich versuche, die Spaghetti … erm, den Code in Lazarus zu importieren.

Lazarus bietet einen Import von Delphi-Projekten an. Danke, liebe Lazarusentwickler. Der Dank ist ernstgemeint, denn der Import funktioniert gut. Nicht sehr gut, aber gut. Während des Imports zeigt das System bereits mögliche Probleme an, fehlende Units und so kann man sich, Notizen machend, schon einmal darauf einstellen, dass ein einfacher Import wohl sicher nicht den Segen bringt, den man so dringend bräuchte. Ich importierte, notierte, importierte erneut, notierte wieder. Sprang mit meinen Notizen wieder zurück zu Delphi und versuchte, weitere Probleme zu beheben oder zumindest zu minimieren. Commit, Checkout, Import, Notizen.

Irgendwann war ich dann soweit, dass der Import gut durchlief. Das hatte aber auch Tage gedauert. Ich war aber sehr stolz auf mich. Dann klickte ich auf “Kompilieren”. Ich musste noch einige Units entfernen, einige Funktionen und Prozeduren ausklammern, einigen Code umschreiben, aber irgendwann, recht schnell, wenn ich mich recht erinnere, kompilierte das Projekt dann durch. Nachdem ich auch Firebird inklusive Abhängigkeiten am Rennen hatte, haute es mich aus den Socken: Das Ding startete. Es startete. Es kam … tatatataaaa … die Login-Maske. Zumindeste schätzte ich, dass sie es wäre, denn sie war noch leer. Ich schloss den Tag trotzdem als erfolgreich ab. Ich fand dann recht schnell heraus, dass ich teilweise Ressourcen-Dateien ausgeklammert hatte und als ich sie wieder einklammerte und die Endung .dfm in .lfm umschrieb, die Masken (fast) 1:1 so aussahen, wie in Delphi. Ich arbeitete mich langsam vor, Maske für Maske für Maske. Ich wusste, es würde ein langer Weg werden, der noch weitere Stolpersteine haben sollte.

Einer dieser Stolpersteine war tatsächlich, dass einige Masken/Dialoge in Delphi binär und nicht in Textform abgespeichert waren. Komischerweise waren das von gut fünfzig Dialogen fünf oder sechs. Das Problem ist einfach zu lösen. In Delphi 7 öffnet man den Dialog und speichert ihn als Text, so dass man ihn in Lazarus benutzen kann. Dialoge, die per Text beschrieben werden, haben gegenüber den binären Dialogen den entscheidenden Vorteil, dass man sie mit jedem beliebigen Editor öffnen und bearbeiten kann, während sie auch mal aus Inkompatibilität eben nicht mit Lazarus GUI-Editor laden.

Es war eine Menge Tipperei, Ausklammerei, Umschreiben von Code, Entfernen von altem Code und Schreiben von neuem Code. Vor allem einiges an der Datenbankschnittstelle musste geändert werden, da wohl IB nicht hunderprozentig wie IBX funktioniert, vor allem im Transaktionsbereich.

Ich war dann aber sehr stolz, als die gesamte Basis der Software lief und fast so aussah und sich verhielt, wie sie es davor bei Delphi auch tat. Dann kam aber der Teil, der mir am meisten Bauchschmerzen bereitete. Im alten Projekt wurde QuickReport benutzt, um Reports zu generieren, das Drucken zu übernehmen und PDFs zu erzeugen. Gibt es QuickReport nicht mal mehr für ein aktuelles Delphi und ist die alte Version anscheinend nur mit Gefrickel und neueren Delphi-Versionen zum Laufen zu überreden, gibt es das Projekt gar nicht für Lazarus. Das bedeutet: Keine Reports, kein Drucken, kein PDF-Export.

Ich sah mir dann drei oder vier verschiedene kostenlose Report-Generatoren an, die sich über den Lazarus-Online-Packager installieren liessen. Alles unfertig. Der einzige Report-Generator, den ich halbwegs brauchbar fand und finde, heißt FortesReport. Dieser ist sehr nah an QuickReport und lässt sich ähnlich bedienen. Man baut die Reports mit dem Lazarus-GUI-Builder zusammen und kann sie dann aufrufen und mit Daten füllen. Ein Problem gibt es aber an FortesReport, welches nicht zu unterschätzen ist: Die Dokumentation. Diese gibt es nämlich nicht.

Wer mich kennt weiß, ich bin faul. Jemand meinte mal zu mir, alle Programmierer sind faul. Also überlegte ich nach einem Weg, wie ich das QuickReport-Zeugs zum FortesReport-Zeugs konvertiert bekomme. Und während ich so nachdachte, googlte ich und fand jemanden, der das selbe Problem hatte. Ich war nicht alleine auf dieser Welt. DACConv heißt das Programm. Die Software macht nicht viel mehr, als in den Pascal-Dateien und in den LFM-Dateien Klassennamen und Variablennamen anhand bestimmter mitgelieferter Schemata auszutauschen. Abgesehen von der echt schlechten Bedienung der Software macht sie ihren Job aber fein. Nur leider bleibt Handarbeit nicht erspart, denn teils müssen Bänder umgebaut werden, teils müssen Objekte entfernt werden, die einfach von FortesReport nicht unterstützt werden. Aber es geht allemal schneller, sehr viel schneller, als die Reports vollständig von Hand neuzubauen.

Ist das alles geschafft, kann man stolz auf sich sein. Das Projekt lässt sich reproduzierbar kompilieren und läuft und auch die Reports sehen aus, wie im Original.

Ist das alles also einfach gewesen? Nein. Man benötigt bereits einiges an Erfahrung, viel Sitzfleisch und, am Wichtigsten: Nerven wie Drahtseile.

Was ich allerdings sagen muss: Lazarus und FreePascal sind sehr stabil und sehr brauchbar, das hätte ich so nicht gedacht. In all der Zeit ist mir Lazarus vielleicht vier oder fünf Mal abgestürzt, und es war nicht einmal schlimm, da keine Daten dadurch beeinträchtigt wurden. Sie sollten noch ein wenig an der Stabilität feilen, aber ich könnte mir vorstellen, damit noch einmal zu arbeiten. Vielleicht nicht an einem großen Projekt, aber an kleinen Tools.

Neues YouTube-Video – Qt-Tutorial 001: Vorstellung

Ich habe ein neues Video hochgeladen. In meinem Qt-Tutorial geht es darum, das Framework kennenzulernen und damit zu arbeiten.

Qt-Tutorial 001: Vorstellung

In diesem Video gehe darauf ein, was wir mit Qt in diesem Tutorial machen werden.

Nur kurz zusammengefasst: Bei Qt handelt es sich um ein Anwendungsframework und eine GUI-Bibliothek, sprich, man kann einfach Software in C++ (und anderen Programmiersprachen) schreiben, die auch über eine grafische Benutzeroberfläche verfügen.

Qt gibt es für etliche Betriebssystem. Neben Windows, macOS und Linux gibt es auch (teils inoffizielle Builds) für bsplw. Haiku und FreeBSD und andere.

Zusätzlich zur GUI-Bibliothekt gibt es aber auch viele weiter Abstraktionen wie Netzwerk, Multimedia, Datenbanken und vieles mehr.

In diesem Tutorial geht es um folgende Dinge:

  • Erstellung eines kostenlosen Kontos auf https://qt.io, um die Installation aus den offiziellen Quellen durchzuführen
  • Installation von Qt auf
    • Windows
    • macOS
    • Linux
  • GUI-Entwicklung
  • Netzwerk-Entwicklung (Sockets)
  • Datenbankanbindung

Alles andere lasse ich in diesem Tutorial aber zuerst aus, sprich, ich gehe weder auf Multimediaentwicklung (Kameraansteuerung, Mikrofon und ähnliches), QML, Entwicklung für mobile Endgeräte und Embedded-Entwicklung ein.

Viel Spaß beim Zusehen.

Mein YouTube-Kanal

Ich habe es getan, ich habe es wirklich getan. Nachdem manche meinten, ich solle einen YouTube-Kanal aufmachen, und ich immer sagte: “Ich kann sowas nicht, ich kann ja nichtmal vernünftig frei reden.” und mir gesagt wurde: “Jeder hat mal klein angefangen, da wächst du schon hinein.” habe ich für mich beschlossen, ich beginne mal einfach und schaue, was daraus wird.

Ich habe bereits ein paar Videos vorproduziert. Natürlich, wie ich auch erwartet habe, sind sie noch schrecklich. Wenn ich aber nicht anfange und einfach mache, dann kann ich natürlich auch nicht besser werden. Also seid ein wenig nachsichtig (:

Ich werde mit drei, vielleicht vier, Sparten beginnen:

  • Softwareentwicklung mit Qt
  • FreeBSD
  • Kurztipps
  • und, vielleicht etwas später, macOS-Administration im Netzwerk mit Deployment und vielem mehr

Hier geht es zu meinem YouTube-Kanal: Thorsten Geppert

Mein erstes YouTube-Video – Kurztipp: RollerCoaster Tycoon 2 mit OpenRCT2

Ich habe begonnen. Mein erstes Video ist online. Gestotter, schlecht gesprochen, schlimm geschnitten und ein noch hässlicheres Vorschaubild.

Titel-Bild von RollerCoaster Tycoon 2

Aber, irgendwie muss man ja mal anfangen. Ich bin fleissig dabei und übe, übe, übe. Ich habe mich jetzt getraut, einmal das Video hochzuladen: Link zum Video.

In dem Video geht es um das Spielen von RollerCoaster Tycoon 2 auf modernen Geräten im Jahr 2022. Dazu zeige ich, wie man mit OpenRCT2 und dem Installationspaket von GOG.com das Spiel einfach zum Laufen bekommt.

wxWidgets auf macOS installieren

wxWidgets lässt sich einfach auf dem Mac installieren. Hier das Beispiel für Monterey.

Zuerst checken wir via Git den Code des aktuellen Projekts aus

git clone https://github.com/wxWidgets/wxWidgets.git

Dann wechseln wir in das ausgecheckte Verzeichnis

cd wxWidgets

und checken noch einige Submodule aus

git submodule update --init 3rdparty/nanosvg
git submodule update --init 3rdparty/catch
git submodule update --init src/jpeg
git submodule update --init src/png
git submodule update --init 3rdparty/pcre

Wir erstellen das Verzeichnis, in das hineinkompiliert werden soll, und wechseln dorthin

 mkdir osx && cd osx

Dann konfigurieren wir noch das Projekt, kompilieren und installieren es

../configure --disable-shared --enable-stl --with-cxx=14 --with-macosx-sdk=/Library/Developer/CommandLineTools/SDKs/MacOSX11.sdk --enable-optimise --prefix=/usr/local/wxMac --enable-monolithic  --without-libjbig --without-libtiff
make -j4
sudo make install

wxWidgets ist jetzt einsatzbereit.

wxWidgets-Entwicklung mit dem QtCreator (zumindest auf macOS, Linux und FreeBSD)

Es ist kaum zu glauben, aber bis vor einer kurzen Zeit benutzte ich keine IDE. Oftmals entwickle ich immer noch gerne ohne IDE, doch für Qt nehme ich QtCreator und ich finde die IDE ganz “nett”. Ich kenne etliche Systeme, und keins gefällt mir tatsächlich so gut wie QtCreator, außer NetBeans für Java vielleicht. Damit bin ich aber vermutlich allein (:

Ich wollte einmal wissen, wie hoch der Aufwand ist, wxWidgets in QtCreator einzubinden. Es ist sehr einfach. Wie es geht, zeigt dieser Artikel.

wxWidgets nutzt auf unixoiden System “wx-config” als Kommandozeilenkonfigurationswerkzeug. Das bedeutet, dass man einfach in seinen Compileraufruf “wx-config” einbaut. Ein einfaches Beispiel könnte:

# c++ *.cpp -o test `wx-config --libs --cppflags`

sein.

Also einfach mal den QtCreator starten und ein neues Konsolenprojekt erstellen. In der Projektdatei (*.pro) dann folgende Zeilen hinzufügen:

INCLUDEPATH += /usr/local/wxWidgets/include/wx-3.0
wxCXXFLAGS = $$system(/usr/local/wxWidgets/bin/wx-config --cxxflags --unicode=yes --debug=no)
wxLinkOptions = $$system(/usr/local/wxWidgets/bin/wx-config --debug=no --libs --unicode=yes)
LIBS += $$wxLinkOptions
QMAKE_CXXFLAGS_RELEASE += $$wxCXXFLAGS
QMAKE_CXXFLAGS_DEBUG += $$wxCXXFLAGS

Es ist natürlich darauf zu achten, dass der Pfad für wx-config sowie der Includepfad stimmen und angepasst werden.

Jetzt ist es möglich, einfach sein wxWidgets-Programm zu schreiben und mit Klick auf den Play-Button zu kompilieren und zu starten.

Hier noch ein kleines wxWidgets-C++-Beispiel:

#include <wx/wx.h>

class MyApp : public wxApp {

	public:
		bool OnInit();

};

IMPLEMENT_APP(MyApp)

class MyFrame : public wxFrame {

	public:
		MyFrame();
	
	private:
		enum {
			HELLO_WORLD_BUTTON
		};
	
		wxPanel *mainPanel;
		wxBoxSizer *mainBoxSizer;
		wxButton *helloWorldButton;
		wxTextCtrl *helloWorldTextCtrl;
	
	protected:
		DECLARE_EVENT_TABLE()
		
		void HelloWorldEvent(wxCommandEvent &WXUNUSED(event));

};

bool MyApp::OnInit() {
	MyFrame *f = new MyFrame;
	f->Show();
	SetTopWindow(f);
	return true;
}

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_BUTTON(HELLO_WORLD_BUTTON, MyFrame::HelloWorldEvent)
wxEND_EVENT_TABLE()

MyFrame::MyFrame() : wxFrame(NULL, -1, _("Hello World")) {
	mainPanel = new wxPanel(this, -1);
	mainBoxSizer = new wxBoxSizer(wxHORIZONTAL);
	
	helloWorldButton = new wxButton(mainPanel, HELLO_WORLD_BUTTON, _("Say Hello World"));
	mainBoxSizer->Add(helloWorldButton);
	
	mainBoxSizer->AddSpacer(5);
	
	helloWorldTextCtrl = new wxTextCtrl(mainPanel, -1);
	mainBoxSizer->Add(helloWorldTextCtrl);
	
	mainPanel->SetSizer(mainBoxSizer);
	mainBoxSizer->SetSizeHints(this);
}

void MyFrame::HelloWorldEvent(wxCommandEvent &WXUNUSED(event)) {
	helloWorldTextCtrl->SetValue(_("Hello World"));
}