windows.h -> Anwendung schließt sich nicht ordnungsgemäß -> ich behandle zwei Windows gleichzeitig
-
Du brauchst eigentlich auch nur eine Message Pump, die in der Main Methode sollte völlig ausreichen. jetzt, wo du schreibst, dass eine
while
Schleife nicht terminiert ist auch klar, warum nicht. Beide Schleifen arbeiten auf derselben Message Queue, aber nur eine von beiden bearbeitet dieWM_QUIT
Nachricht und bricht ab.GetMessage
entfernt die Nachricht, die sie ausliest, daher kann sie nur von einer der beiden Schleifen behandelt werden.
Lange Rede, kurzer Sinn: Benutz´ nur eine Message Pump pro Message Queue.PS:
Weil jedes Fenster beim SchließenPostQuitMessage
aufruft wird die Anwendung beendet, sobald eins der beiden Fenster geschlossen wird. Ist das so beabsichtigt?
-
Okay, danke.. das ergibt auf jedenfall Sinn. Ich habe noch nicht so ganz den Durchblick..
- Nein, beabsichtigt ist das nicht. Ist mir allerdings auch nicht aufgefallen, da ich nach dem Schließen (egal welches von den Fenstern), das bestehen bleibende immer noch bedienen kann.
-> Mein Ziel ist kurz gesagt... Wie bei fast jedem Programm, dass über diesen "Info" Button ein kleines Fenster mit Infos über das Programm erscheint.
-
Kannst du mir bitte erläutern was "Eine Message Bumb pro Message Queue" bedeutet ?
Ich habe die Begriffe mal gegoogled, verstehe den Hintergrund aber nicht genau
-
Eine Message Pump (oder Message Loop) ist das Verarbeiten der Nachrichten einer Message Queue. Zumindest der Haupthread einer Windows-Anwendung besitzt eine Message Queue, über die das Verhalten der Anwendung und der zugehörigen Fenster gesteuert wird. Diese Message Queue wird durch Benutzerinteraktion (Tastatur, Maus) oder mit vom System erzeugten Nachrichten automatisch befüllt, dazu musst du als Anwender nichts programmieren. Aber um Nachrichten aus der Queue zu entfernen und zu bearbeiten brauchst du eine Message Pump (oder Loop), die oft so aussieht:
MSG message; while( GetMessage( &message, nullptr , 0, 0 ) ) { TranslateMessage( &message ); DispatchMessage( &message ); }
Wenn du dir die Doku zu
GetMessage
ansiehst wirst du sehen, dass nicht alle Situationen abdeckt und der Codeblock richtigerweise so aussehen sollte:MSG message; while( BOOL success = (GetMessage( &msg, nullptr, 0, 0 ) > 0) ) { if( success ) { TranslateMessage( &msg ); DispatchMessag( &msg ); } else { // Fehler bei GetMessage oder WM_QUIT empfangen } }
Wenn du für das Fensterhandle
nullptr
einsetzt werden alle Nachrichten der Message Queue bearbeitet.MSDN Doku zu GetMessage
MSDN Doku zu Message Queues
-
Das hat mir sehr geholfen. Dank des Tipps mit dem nullptr, funktioniert es super. Danke dir.
- Nun werden allerdings beide Fenster geschlossen, sobald ich eins schließe, da WM_DESTROY ja für beide Windows gleich gilt. Ich bin mir nicht sicher, aber nun kann ich die Windows ja nicht mehr unterscheiden und unabhängig schließen, oder ?
Nutze ich aber nicht den nullptr, sondern das WindowHandle, kann ich wiederum nur ein Fenster mit der Message Pump behandeln.. und dadurch ist das Fenster, welches ich nicht mit der Message Pump abarbeite, gefreezed
-
Die
MSG
Struktur hat ein Feldhwnd
, damit kannst du prüfen, ob die Nachricht für dein Fenster bestimmt war oder nicht.Ich hab schon ewig nicht mehr sowas von Hand programmiert, bin mir jetzt auch nicht sicher, wie man sowas sauber löst. Du könntest dein Hauptfenster das Infofenster schließen lassen, das könnte auch funktionieren:
case WM_QUIT: DestroyWindow( hInfoWindow ); HInfoWindow = nullptr; ... break;
Dazu müsste das hInfoWindow wieder eine globale Variable sein. Ist wohl doch etwas kniffliger, als gedacht.
-
Dieser Beitrag wurde gelöscht!
-
In den Nachrichtenbehandlungsfunktionen überprüfst du einfach, ob der HWND Parameter mit dem HWND Wert der Nachricht übereinstimmt.
-
@TKuehn Du musst natürlich nicht PostQuitMessage bei beiden Fenstern ausfrufen. Bei dem Info-Fenster würde sich anbieten, dieses mit DestroyWindow zu zerstören.
Oder man könnte dieses Fenster nur einmal erzeugen und dann nur per ShowWindow ein oder ausblenden (ausblenden dann natürlich als Reaktion im WM_CLOSE-Zweig).
Typischerweise würde man für einen Infodialog auch kein vollwertiges Fenster erzeugen sondern eben - naja eben einen Dialog.
Dein GetMessage sollte als HWND auch nullptr (oder NULL) übergeben. Bei einem ungültigen Handle kann GetMessage -1 (obwohl BOOL) zurückliefern. Das wurde vor Jahrzehnten mal geändert und dient eigentlich als gutes Beispiel, dass es nicht immer eine gute Idee ist, nachträglich noch Dinge bei so fundamentalen Sachen zu ändern.
-
@DocShow: Deine Abfrage auf
success
ist aber falsch (da bei dir-1
auch als erfolgreich angesehen wird).
Daher auch in der Doku die explizite Abfrage auf-1
bzw. andersherum:if ( success > 0)
Oder wenn man auch im Fehlerfall die Schleife beenden will:
while( GetMessage( &msg, hWnd, 0, 0 ) > 0)
-
@Th69
Autsch, ja.
-
@yahendrik Ohja, danke. Ich wusste nicht, dass es an dem PostQuitMessage(0) liegt.
Nun funktioniert es, wie ich es mir vorgestellt habe
Danke an alle Antworten!