Entschuldigt das Aufkochen; war im Urlaub.
starcow hat geschrieben: ↑14.07.2024, 11:48Ein Gedanken der mir noch gekommen ist:
Man könnte vielleicht Windows dazu bringen, in regelmässigen Abständen (über einen Tick) die Callback Funktion aufzurufen - und dann an diesem Ort die Nachrichtenschleife bearbeiten. Das müsste dann zwar zu einer Rekursion führen, jedoch nur über zwei "Ebenen", wenn man entsprechende Massnahmen (in der Callback) trifft.
Aber vielleicht übersehe ich jetzt noch einen entscheidenden Punkt und die Idee kann ab in den Papierkorb. :-)
Der entscheidende Punkt, den du übersiehst, ist: Timer werden ebenfalls von der Nachrichtenschleife ausgelöst. Bearbeitest du keine Nachrichten, wird auch der Timer nicht ausgelöst. Kann also in den Papierkorb.
Wie gesagt erfordern auch SDL und Qt, dass dein Thread die Nachrichtenschleife aufruft ("Pumping messages").
Falls das aus NytroX' Antwort nicht klar wurde: Dein Thread bekommt erst eine Message Queue, sobald du ein Fenster erzeugst (Sonderfälle außen vor). Du musst also gewöhnlich auch nur so lange Nachrichten verarbeiten, wie Fenster existieren. Keine Notwendigkeit, das schon ab
RegisterClass() zu tun.
Falls es zum Verständnis hilft: Einige Win32-Funktionen pumpen indirekt Nachrichten. Etwa
MessageBox() (sonst würde dein Fenster nicht mehr gezeichnet werden, während eine Message Box darüber liegt) oder
CreateWindow() (sonst könnten
WM_CREATE & Co. nicht abschließen, bevor die Funkion zurückkehrt).
Das Nicht-bearbeiten der Message Queue
hat systemweite Auswirkung. Beispielsweise holt sich Alt+Tab dein Programmsymbol und die Echtzeitvorschau durch Nachrichten. Hängt ein Programm, rennt das in einen Timeout und die Alt+Tab-Liste zeigt nur Platzhalter, oder öffnet stark verzögert.
Das Ändern von Windows-Einstellungen wird ebenfalls via Nachricht an alle Programme gebroadcastet. Änderst du über die Systemeinstellungen deine Vordergrundfarbe, aber ein Fenster hängt und bearbeitet die entsprechende
WM_DWMCOLORIZATIONCOLORCHANGED-Nachricht nicht, dauert es mitunter eine Minute (Timeout) bis die Farbänderung überall ankommt.
Jetzt zur ganz ursprünglichen Frage: Zum Kapseln der Nachrichtenschleife. Das ist AFAIK nicht Fenster-agnostisch möglich, weil die Nachrichtenschleife
pro Fenster unterschiedlich aussieht. Du kennst ja bspw. die Keyboard Shortcuts Strg+S für
Datei > Speichern usw.? Damit die funktionieren, musst du
TranslateAccelerator() mit einer Tabelle der möglichen Tastenkürzel aufrufen - und zwar
direkt nach GetMessage() und vor DispatchMessage(). Du musst also innerhalb der Nachrichtenschleife wissen, welche Tastenkürzeltabelle das Fenster erfordert, für das die nächste Nachricht bestimmt ist. (Selbes mit
IsDialogMessage(), falls du innerhalb deines Fensters mit Pfeiltasten/Tab navigieren möchtest; falls die Return-Taste den Standardknopf drücken soll; usw.)
Ich habe bisher absolut keine zufriedenstellene Möglichkeit gefunden, das zu abstrahieren. Du kannst eine thread-lokale globale Variable anlegen, die dir das mappt, und dann hoffen, dass sich alle Fenster dort eintragen.
Das nur als Beispiel, auf was für Hürden du stößt, wenn du die Nachrichtenschleife zu kapseln versuchst.
Qt, WinUI, Firefox/Chrome umgehen das, indem sie Windows-Nachrichten nur für das Nötigste benutzen. Alle Buttons, Toolbars, Texte usw. sind nicht als Win32-Objekte realisiert, sondern werden auf die Zeichenfläche des Parent-Fensters gemalt. Das erfordert gigantischen Aufwand, um so etwas wie Screen Reader für Sehbehinderte zu unterstützen. Außerdem bekommt man den neuesten App-Look (abgerundete Kanten etc.) nicht automatisch, sondern muss das immer selber implementieren. Dass du sauber kapseln kannst, ist dann aber Vorteil von "wir machen eine komplette GUI selber from Scratch".