Wie funktionieren GUI Toolkits?

Hallo
Ich hab da mal eine Frage:
Wie funktionieren GUI-Toolkits?
Eine Möglichkeit wäre, die API des jeweiligen OS zu nutzen. Aber die TK Bibliothek (z.B.) ist auf allen Plattformen als eine Version verfügbar.
Eine andere Möglichkeit wäre, den Videospeicher zu nutzen, der ist aber schon durch das OS genutzt.
Noch eine Möglichkeit, die mir einfällt, ist, dass die Toolkits Grafiken „laden“ und dann anstatt der Konsole laden lassen. Aber WIE?
Ich hoffe, ihr könnt mir helfen (bzw. mir das erklären).
Vielen Dank schon jetzt.
mfg
hahihu

Hallo
Ich hab da mal eine Frage:
Wie funktionieren GUI-Toolkits?
Eine Möglichkeit wäre, die API des jeweiligen OS zu nutzen.

So wird das in der Regel gemacht. Um etwas auf den Bildschirm zu bringen, muss irgendwann jemand etwas mit der Hardware anstellen, und das ist nicht das Userspace-Programm, sondern Kernelcode.

Aber die TK Bibliothek (z.B.) ist auf allen Plattformen als
eine Version verfügbar.

Solche Bibliotheken bringen in der Regel mehrere Anbindungen an verschiedene Betriebssystem-APIs mit. Wenn du TK auf MacOS kompilierst, werden andere Codestücke verwendet als unter Solaris.

Eine andere Möglichkeit wäre, den Videospeicher zu nutzen, der
ist aber schon durch das OS genutzt.

…und für das Userspace-Programm überhaupt nicht zu erreichen. Und wäre er zu erreichen, wüsste das Programm nicht, was es mit dem Speicher anfangen soll, das weiß nur der Treiber.

Noch eine Möglichkeit, die mir einfällt, ist, dass die
Toolkits Grafiken „laden“ und dann anstatt der Konsole laden
lassen. Aber WIE?

Welche Konsole?

Ich hoffe, ihr könnt mir helfen (bzw. mir das erklären).
Vielen Dank schon jetzt.

Auf der untersten Ebene wird das Problem der verschiedenen Platformen z.B. mit #defines gelöst, oder es werden im Build-Prozess je nach Plattform Dateien ausgewählt, die Funktionen bereitstellen, die die jeweilige Platform „wegabstrahieren“.

Ersteres z.B. so:

#ifdef WIN32
void ZeichnePunkt(int x, int y)
{
SchedulePointDrawingMessageQueueEventCallbackEx(NULL, x, y, g_hWnd);
}
#else
void ZeichnePunkt(int x, int y)
{

}
#endif

Viele Grüße,
Sebastian

Vielen Dank!
Das hat mir sehr geholfen.

Aber eins versteh ich immer noch nicht so ganz:
Mal angenommen, es gibt eine Funktion namens

mache\_button(char text[], int x\_groesse, int y\_groesse, int x\_pos, int y\_pos)
{
//...
}

Um die WinAPI zu nutzen, braucht man ja eine WinMain Funktion und eine WindowsProzedur. Aber wenn man jetzt diese Funktion aufruft, wo sind denn die beiden Funktionen deklariert?
Danke auch schon jetzt.
mfg
hahihu

Um die WinAPI zu nutzen, braucht man ja eine WinMain Funktion
und eine WindowsProzedur. Aber wenn man jetzt diese Funktion
aufruft, wo sind denn die beiden Funktionen deklariert?
Danke auch schon jetzt.

Das GUI-Toolkit wird dir in der Regel eine Funktion anbieten, die die Eventschleife startet. Also bei Windows die Message-Pumperei, bei einem anderen System etwas anders. Es läuft dann so ab, dass du die gewünschten Buttons, Menüs und sonstige Dinge erstellst und mit den Ereignissen wie „Button geklickt“ Ereignisbehandlungen verknüpfst. Wenn das steht, wird eine Methode des GUI-Toolkits aufgerufen, die sich um den Rest kümmert, also das Fenster und seine Inhalte über die OS-GUI-API darzustellen und interessante Ereignisse abzufangen und an die Handler weiterzuleiten.

Viele Grüße,
Sebastian

Das GUI-Toolkit wird dir in der Regel eine Funktion anbieten,
die die Eventschleife startet.

Also z.B. start_message();

Also bei Windows die
Message-Pumperei, bei einem anderen System etwas anders. Es
läuft dann so ab, dass du die gewünschten Buttons, Menüs und
sonstige Dinge erstellst und mit den Ereignissen wie „Button
geklickt“ Ereignisbehandlungen verknüpfst. Wenn das steht,
wird eine Methode des GUI-Toolkits aufgerufen, die sich um den
Rest kümmert, also das Fenster und seine Inhalte über die
OS-GUI-API darzustellen und interessante Ereignisse abzufangen
und an die Handler weiterzuleiten.

Und diese start_message() sorgt dann unter Windows z.B. dafür, dass eine Funktion namens WinMain gestartet wird und eine WinProc eingerichtet wird, obwohl es schon durch den Benutzer eine main-Funktion gibt?
mfg
hahihu

Und diese start_message() sorgt dann unter Windows z.B. dafür,
dass eine Funktion namens WinMain gestartet wird und eine
WinProc eingerichtet wird, obwohl es schon durch den Benutzer
eine main-Funktion gibt?

Die Funktion, die die Nachrichten pumpt, muss ja nicht WinMain heißen. Ich bin mir im Moment nicht sicher, welche Funktion Windows gerne als Einsprungpunkt hätte. Ich hätte nämlich gedacht, dass die Ausführung von Usercode bei einer Fensterle-Anwendung schon direkt bei WinMain() beginnt (statt bei main() wie normal üblich). Dann wäre WinMain() ohnehin durch den Ersteller der einzelnen Anwendung belegt, und die Message-Pumpe würde eben in einer anders benannten Funktion des GUI-Toolkits ablaufen. D.h. Otto Anwendungsprogrammierer würde WinMain() schreiben, dort Dinge mit dem GUI-Toolkit tun und am Schluß die Kontrolle mit Aufruf von „start_message()“ an es weiterreichen. „start_message()“ würde wohl erst zurückkehren, wenn die Applikation geschlossen wird. Um diese WinProc etc. würde sich start_message() dann auch kümmern.

Der Usercode wäre in dem Fall durch die Verwendung von WinMain() statt main() nicht ganz portabel, der Programmierer würde selbst noch ein plattformabhängiges #ifdef o.ä. verwenden müssen.

Falls Windows auch bei grafischen Anwendungen in der Lage ist, mit main() zu beginnen, erübrigt sich das Problem.

Viele Grüße,
Sebastian

Nochmals vielen Dank, jetzt ist mir einiges viel klarer geworden!

Soweit ich weiß, klappt das bei Windows so:
Es gibt keine main Funktion, sondern nur eine WinMain Funktion. In dieser wird die Fensterklasse deklariert, inkl. aller Eigenschaften (Rahmen, Größe, etc.). Dort wird auch eine Fensterinstanz erzeugt. Danach wird eine Message-Abfang-Schleife gestartet, eine sog. Windows-Prozedur (die kann beliebig heißen). Dieser Funktion wird die Instanznummer des betroffenen Fensters als Parameter übergeben und die jeweilige Message. Diese wird dann bearbeitet.
Sobald die Nachricht der Aufforderung zum Beenden kommt, wird die Abfangschleife unterbrochen und man kehrt zu WinMain zurück. Danach gibt es keine Anweisungen mehr und das Programm wird beendet.

Soweit ich weiß, klappt das bei Windows so:
Es gibt keine main Funktion, sondern nur eine WinMain
Funktion. In dieser wird die Fensterklasse deklariert, inkl.
aller Eigenschaften (Rahmen, Größe, etc.). Dort wird auch eine
Fensterinstanz erzeugt. Danach wird eine
Message-Abfang-Schleife gestartet, eine sog. Windows-Prozedur
(die kann beliebig heißen). Dieser Funktion wird die
Instanznummer des betroffenen Fensters als Parameter übergeben
und die jeweilige Message. Diese wird dann bearbeitet.
Sobald die Nachricht der Aufforderung zum Beenden kommt, wird
die Abfangschleife unterbrochen und man kehrt zu WinMain
zurück. Danach gibt es keine Anweisungen mehr und das Programm
wird beendet.

So hatte ich das auch in Erinnerung. Die Abfangschleife etc. kann natürlich genausogut in einer Unterfunktion stehen, und dort landet sie bei einem GUI-Toolkit eben.

Damit der Code portabel bleibt, muss man es als Anwendungsprogrammierer wohl am besten so ähnlich wie folgt machen:

#ifdef WIN32
int WinMain(…)
{
return main(…);
}
#endif

int main(int argc, char** argv)
{
// buttons erzeugen etc
// […]
guitoolkit_start_messageloop();
return 0;
}

Viele Grüße,
Sebastian

Jop.
Danke für die Antworten!
mfg
hahihu