WM_CLOSE -> Verständnisfrage

Skid

Erfahrenes Mitglied
Hallo zusammen,

ich habe eine Verständnisfrage, zu der WM_CLOSE-Message. Und zwar, bekomme ich ja diese Nachricht, wenn das Fenster geschlossen werden soll beispielsweise durch das drücken des "X" in der rechten oberen Ecke. In meiner Anwendung prüfe ich in der WndProc-Funktion speziell nach dieser Nachricht und sende eine Quit-Message mit ...

Code:
PostQuitMessage(0);

Anschließend füge ich ein "break;" für die Switch-Anweisung an, damit aus dieser herausgesprungen wird. Am Ende der Funktion wird folgendes zurückgegeben:

Code:
return DefWindowProc(pHWND, pMsg, pWParam, pLParam);

Soweit so gut. Wenn ich jetzt allerdings das Programm beende und demnach den Device Context lösen möchte, bekomme ich den Error 1425 und natürlich gleichsam für das zerstören des Fensters den Error 1400. Soll heißen:

Code:
1425 = Invalid device context (DC) handle.
1400 = Invalid window handle.

Wenn ich allerdings, durch das Drücken der ESC-Taste eine PostQuitMessage versende, bekomme ich diesen Fehler nicht. Wenn ich jetzt in der WndProc die Break-Anweidung durch return 0 ersetze, bekomme ich weder beim drücken der ESC-Taste, noch beim drücken des "X" eine Fehlermeldung.

Woran liegt das?
Zuvor hatte ich OpenGL und die Windows-Funktionen in zwei separaten Klassen getrennt und da ging es auch, jetzt allerdings durch das zusammenlegen nicht mehr. Ich muss jedoch dazu sagen, dass zuvor dieser Return-Wert "DefWindowProc" in der default-Marke der Switch-Anweisung zurückgegeben wurde.

Vielen Dank,
SKiD.
 
Hi.

Normalerweise solltest du nur die Nachrichten überschreiben, deren Verhalten du ändern willst.

Die Standard-Windows-Prozedur ruft bei der WM_CLOSE Nachricht DestroyWindow auf, welches seinerseits WM_DESTROY Nachrichten versendet.

Üblicherweise behandelt man die WM_DESTROY Nachricht und ruft daraufhin PostQuitMessage auf.

Wenn du eine Nachricht behandelt hast, solltest du (normalerweise) nicht noch extra die DefWindowProc aufrufen.

Gruß
 
Ach so, also wenn ich das richtig verstanden habe, dann wird die DefWindowProc aufgerufen oder sollte aufgerufen werden, wenn eine Nachricht nicht explizit in der Switch-Anweisung behandelt wurde, zum Beispiel in der Default-Marke oder als Rückgabewert, während alle anderen Marken "return 0" zurückgeben.

Also ungefähr so:
Code:
LRESULT CALLBACK WndProc(...)
{
  switch(tMsg)
  {
      WM_CLOSE: \\ tu was
                           return 0;
      WM_SIZE: \\tu was
                       return 0;
  };

  return DefWindowProc(...);
}

oder so:
Code:
LRESULT CALLBACK WndProc(...)
{
  switch(tMsg)
  {
      WM_CLOSE: \\ tu was
                           break;
      WM_SIZE: \\tu was
                       break;
       default:   return DefWindowProc(...);
  };
}

Das Problem bei meiner Geschichte wäre ja dann, dass das Fenster zerstört wurde, bevor ich die Methoden "ReleaseDC" und "DestroyWindow" in meinem Destruktor aufgerufen habe, oder? Da das drücken des X-Symbols ja schon vorher die DefWindowProc aufruft und das Fenster standardmäßig zerstört wurde.
 
Nein, nein, nein. Return 0 ist KEIN Standard für behandelte Nachrichten. (Dafür könnte ich die Visual Studio Wizard Win32-Projekt-Erstellen kloppen) Es hängt vollkommen von der Nachricht selbst ab, immer in der Doku nachsehen.
Grundsätzlich solltest du bei ALLEN Nachrichten, auch bei denen, die du behandelts, DefWindowProc aufrufen. Es sei denn, es steht explizit in der Doku, dass man das nicht machen soll. Deshalb ziehe ich auch ganz klar deine erste Variante vor.

Du kannst dein ReleaseDC in WM_DESTROY aufrufen. WM_DESTROY ist im Gegensatz zu WM_CLOSE eine Notification, keine Aktionsnachricht.
 
Grundsätzlich solltest du bei ALLEN Nachrichten, auch bei denen, die du behandelts, DefWindowProc aufrufen. Es sei denn, es steht explizit in der Doku, dass man das nicht machen soll. Deshalb ziehe ich auch ganz klar deine erste Variante vor.
Da sind wir wohl unterschiedlicher Meinung...
MSDN hat gesagt.:
Calls the default window procedure to provide default processing for any window messages that an application does not process.
Mir fällt gerade auf, das es evtl. etwas missverständlich sein könnte von "verarbeiteten Nachrichten" zu sprechen.

Ich meine damit Nachrichten, die eine Anwendung selbst behandelt.

Man kann natürlich auch auf Nachrichten reagieren (diese verarbeiten) und trotzdem die normale Aktion durchführen.

WM_CLOSE ist eigentlich ein Paradebeispiel, man kann es selbst behandeln (und einfach ignorieren), oder den Nutzer fragen ob wirklich abgebrochen werden soll und in dem Fall DefWindowProc aufrufen.

Gruß
 
WM_CLOSE ist ein gutes Beispiel. Man kann es selbst behandeln (etwas auf WM_CLOSE hin auslösen) und dann die Standard-Behandlung (das Fenster zerstören) von DefWindowProc auslösen lassen.

Versuch mal, Maus-Nachrichten nicht weiterzuleiten. Da läuft man dann durchaus in Fokusprobleme u.Ä., wenn man nicht alle weiterleitet.

Mit "Process message" meint die MSDN eher, daß man das übliche Verhalten von DefWindowProc durch etwas Eigenes ersetzt, das aber auch das Standard-Verhalten abdeckt. Wenn man das abdeckt, kann bzw. muß man direkt mit return raus.
Wenn man aber nur ein paar Variablen setzt, dann sollte man immer DefWindowProc nachsetzen.

Bezüglich des generellen return 0, das ist zum Beispiel bei WM_ERASEBKGND eine ganz schlechte Idee.
 
Zurück