wxWidgets-Minimalprogramm
Willemers Informatik-Ecke
Weitere Themen

Hello World

Um einen Anfang zu finden, stellen viele Systeme in Tradition zum ersten C-Buch ein Hello-World-Programm dar, das nur die Welt grüßt. Auch die offizielle wxWidgets-Doku stellt ein solches Programm zur Verfügung. Allerdings enthält es auch gleich ein Menü.

Minimal-Programm

Das folgende Programm reduziert das Hello-World um die Menüs und ist damit beinahe kleinstmöglich.

Es wird die Klasse wxApp abgeleitet. Diese eigene App überschreibt die Methode OnInit. Dort wird ein Fenster erzeugt und über die Methode show angezeigt. Die main-Funktion verbirgt sich hinter wxIMPLEMENT_APP.

Das eigene Fenster wird von wxFrame abgeleitet. In seinem Konstruktor erzeugt es eine Statusleiste, die mit einem Text gefüllt wird. Der Konstruktor ruft den Konstruktor von wxFrame. Im dritten Parameter wird der Text der Titelleiste übergeben.

#include <wx/wx.h>
  
class MiniApp : public wxApp
{
public:
    virtual bool OnInit();
};

class Fenster : public wxFrame
{
public:
    Fenster();
};

wxIMPLEMENT_APP(MiniApp);

bool MiniApp::OnInit()
{
    Fenster *fenster = new Fenster();
    fenster->Show(true);
    return true;
}

Fenster::Fenster() : wxFrame(NULL, wxID_ANY, "Hallo Welt")
{
    CreateStatusBar();
    SetStatusText("Dieses Programm ist sehr klein!");
}

Fensterereignisse

Wir wollen das Mini-Programm dahin erweitern, dass es auf Mausklicks reagiert und an der Mausposition einen Kreis malt.

Bei größeren Programmen ist es natürlich, App und Frame zu trennen. Die Ableitung von wxApp wird hier in einer eigenen Datei abgelegt.

#include <wx/wx.h>
#include "wxKreisClickFrame.h"

class wxKreisClickApp : public wxApp {
    public:
        virtual bool OnInit();
};

IMPLEMENT_APP(wxKreisClickApp)

bool wxKreisClickApp::OnInit()
{
        wxKreisClickFrame *frame = new wxKreisClickFrame(
            ("KreisClick"), wxPoint(50,50),
            wxSize(400, 300));

        frame->Show(TRUE);
        SetTopWindow(frame);
        return TRUE;
}
In der wxApp wird in erster Linie in der OnInit-Methode das Fenster gestartet. Darum wird die Header-Datei des Frames benötigt.

In der Frame-Include-Datei wird die Frame-Klasse definiert.

#include <wx/wx.h>
class wxKreisClickFrame : public wxFrame {
    public:
        wxKreisClickFrame(const wxString& title,
                         const wxPoint& pos,
                         const wxSize& size);
        void OnMouseEvent(wxMouseEvent& event);
        void OnPaint(wxPaintEvent& event);

    private:
        DECLARE_EVENT_TABLE()
};
Schließlich wird das Frame implementiert. Hier werden nun zwei Events betrachtet: EVT_MOUSE_EVENTS und EVT_PAINT.

Tritt ein EVT_MOUSE_EVENTS auf, wird die Methode OnMouseEvent aufgerufen. Sie hat als Parameter ein wxMouseEvent. Dieser enthält die Mauspostion, die mit GetLogicalPosition ermittelt wird. Das Programm speichert die Position in der Variable glob. Anschließend führt der Aufruf von Refresh dazu, dass ein EVT_PAINT-Event auftritt.

#include <wx/wx.h>
#include "wxKreisClickFrame.h"

BEGIN_EVENT_TABLE( wxKreisClickFrame, wxFrame )
    EVT_MOUSE_EVENTS(wxKreisClickFrame::OnMouseEvent)
    EVT_PAINT(wxKreisClickFrame::OnPaint)
END_EVENT_TABLE()

wxKreisClickFrame::wxKreisClickFrame( const wxString& title, const wxPoint& pos, const wxSize& size )
    : wxFrame((wxFrame *)NULL, -1, title, pos, size)
{
    wxImageHandler *GifHandler = new wxGIFHandler();
    wxImage::AddHandler(GifHandler);
}

wxPoint glob;
bool clicked = false;

void wxKreisClickFrame::OnMouseEvent(wxMouseEvent& event)
{
    wxClientDC dc(this);
    if (event.LeftDown()) {
        wxPoint pt(event.GetLogicalPosition(dc));
        glob = pt;
        clicked = true;
        Refresh();
    }
}

void wxKreisClickFrame::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);
    if (clicked)
        dc.DrawCircle(glob, 5);
    std::cout << ".";
}