DefWindowProc immer als Rückgabewert
-
Standardmäßig wird ja in der WndProc im Default-Zweig immer return DefWindowProc (...) geschrieben, während ganz am Ende der Funktion ein return 0 steht. Nun habe ich mal ein Testprogramm mit ein bißchen Grafik und einigen Windows-Nachrichten geschrieben. Doch das Merkwürdige ist jetzt: Wenn ich es so mache, wie oben beschrieben, funktioniert das Programm nicht richtig, zum Beispiel wird eine Message Box nicht angezeigt, aber trotzdem ist der Fokus des Hauptfensters solange weg, bis ich Enter oder Space drücke (als wäre die Message Box unsichtbar, aber trotzdem vorhanden). Wenn ich allerdings DefWindowProc ganz am Ende immer als Rückgabewert übergebe, egal, welche Nachricht verarbeitet wurde, funktioniert alles, wie es soll.
Wäre es demnach nicht besser, in der WndProc am Ende immer nur ein einziges return mit der DefWindowProc zu machen, statt sie nur für unbehandelte Nachrichten aufzurufen (und den anderen Möglichkeiten ein return 0 zu geben)?
-
Nur zur Sicherheit vorweg: Redest du von Dialogen oder von Fenstern ?
Also normalerweise wird die DefWindowProc NUR für unbehandelte Messages genutzt bzw. aufgerufen. (Beispiel) Du musst also einen Fehler in deinem Programm haben
.
-
Ich rede von regulären Fenstern.
O.k., mein Programm sieht folgendermaßen aus (interessant für das Problem ist, soweit ich sehe, nur die WindowProc:#include <windows.h> LRESULT CALLBACK WindowProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int showCmd) { HWND window; WNDCLASSEX wndClassEx={0}; MSG message; wndClassEx.cbSize=sizeof (wndClassEx); wndClassEx.lpfnWndProc=WindowProc; wndClassEx.hInstance=instance; wndClassEx.hIcon=LoadIcon (NULL, IDI_APPLICATION); wndClassEx.hCursor=LoadCursor (NULL, IDC_ARROW); wndClassEx.hbrBackground=reinterpret_cast<HBRUSH> (NULL_BRUSH); wndClassEx.lpszClassName="Testprogramm"; wndClassEx.hIconSm=wndClassEx.hIcon; RegisterClassEx (&wndClassEx); window=CreateWindowEx (0, wndClassEx.lpszClassName, wndClassEx.lpszClassName, WS_MINIMIZEBOX|WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, instance, NULL); ShowWindow (window, showCmd); UpdateWindow (window); while (GetMessage (&message, NULL, 0, 0)) { TranslateMessage (&message); DispatchMessage (&message); } return message.wParam; } LRESULT CALLBACK WindowProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CLOSE: DestroyWindow (wnd); break; case WM_DESTROY: PostQuitMessage (0); break; case WM_KEYDOWN: MessageBox (wnd, "Hallo", "Message-Box", MB_OK); break; case WM_PAINT: //... (Beliebige Aktionen oder auch gar nichts) break; default: return DefWindowProc (wnd, msg, wParam, lParam); } return 0; }Wenn man das kompiliert und eine Taste drückt, verliert das Fenster den Fokus, es kommt das Geräusch für eine Message-Box, aber es ist keine zu sehen. Trotzdem kann ich diese "unsichtbare Box" mit Enter schließen und das Fenster erhält wieder den Fokus.
Wenn ich den Default-Zweig wegnehme und das return DefWindowProc (...) ganz ans Ende setze, funktioniert alles. Und wenn ich es so lasse, wie es jetzt da steht und nur den WM_PAINT-Zweig komplett auskommentiere, dann geht es auch. Das Problem müßte also bei der Behandlung der WM_PAINT-Nachricht liegen.
-
LOL, jo versuch mal das:
#include <windows.h> LRESULT CALLBACK WindowProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int showCmd) { HWND window; WNDCLASSEX wndClassEx={0}; MSG message; wndClassEx.cbSize=sizeof (wndClassEx); wndClassEx.lpfnWndProc=WindowProc; wndClassEx.hInstance=instance; wndClassEx.hIcon=LoadIcon (NULL, IDI_APPLICATION); wndClassEx.hCursor=LoadCursor (NULL, IDC_ARROW); wndClassEx.hbrBackground=reinterpret_cast<HBRUSH> (NULL_BRUSH); wndClassEx.lpszClassName="Testprogramm"; wndClassEx.hIconSm=wndClassEx.hIcon; RegisterClassEx (&wndClassEx); window=CreateWindowEx (0, wndClassEx.lpszClassName, wndClassEx.lpszClassName, WS_MINIMIZEBOX|WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, instance, NULL); ShowWindow (window, showCmd); UpdateWindow (window); while (GetMessage (&message, NULL, 0, 0)) { TranslateMessage (&message); DispatchMessage (&message); } return message.wParam; } LRESULT CALLBACK WindowProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CLOSE: // nur ein DestroyWindow zerstört das fenster und die Anwendung läuft weiter, was haste davon ?^^ case WM_DESTROY: PostQuitMessage(0); break; case WM_KEYDOWN: MessageBox (wnd, "Hallo", "Message-Box", MB_OK); break; /* case WM_PAINT: // entweder du fängst die Nachricht ab und zeichnest was oder du lässt es^^ break; */ default: return DefWindowProc (wnd, msg, wParam, lParam); } return 0L; }
-
Co-Produktion CodeFinder & NES Spieler schrieb:
// ... default: return DefWindowProc (wnd, msg, wParam, lParam); } return 0L; }
thedaylywtf!?*lol*

Greetz, Swordfish
-
Swordfish schrieb:
thedaylywtf!?*lol*

What ?!
-
Ach ja, da fehlt ja dieses BeginPaint und EndPaint. Danke für den Hinweis.
nur ein DestroyWindow zerstört das fenster und die Anwendung läuft weiter, was haste davon ?^^
Die Anwendung läuft nicht weiter. Die WM_CLOSE-Nachricht ruft ja die WM_DESTROY-Nachricht durch die Funktion DestroyWindow auf, also zumindest habe ich das so verstanden:
case WM_CLOSE: DestroyWindow (wnd); break; case WM_DESTROY: PostQuitMessage (0); break;Warum ich das so mache? Keine Ahnung, so hab ich es in den diversen Tutorials gelesen. Aber die Version, daß man für beide Nachrichten gleichermaßen PostQuitMessage aufruft, geht natürlich auch.
-
CodeFinder schrieb:
LOL, jo versuch mal das:
#include <windows.h> case WM_CLOSE: // nur ein DestroyWindow zerstört das fenster und die Anwendung läuft weiter, was haste davon ?^^ case WM_DESTROY: PostQuitMessage(0); break; }Das ist in jedem Fall falsch! WM_CLOSE sollte DestrowWndow aufrufen oder den Default Handler, der das Selbe tut. Wenn es so gemacht wird wie hier, wird das Fenster nur dadurch zerstört weil die Applikation geschlossen wird. WM_DESTROY würde nie versendet... Es würde keinen korrekten Cleanup geben.
Außerdem haben diese beiden Nachrichten nichts mit dem geschliederten Problem zu tun.
-
NES-Spieler schrieb:
case WM_CLOSE: DestroyWindow (wnd); break; case WM_DESTROY: PostQuitMessage (0); break;Warum ich das so mache? Keine Ahnung, so hab ich es in den diversen Tutorials gelesen. Aber die Version, daß man für beide Nachrichten gleichermaßen PostQuitMessage aufruft, geht natürlich auch.
Das ist auch OK!
-
NES-Spieler schrieb:
Doch das Merkwürdige ist jetzt: Wenn ich es so mache, wie oben beschrieben, funktioniert das Programm nicht richtig, zum Beispiel wird eine Message Box nicht angezeigt, aber trotzdem ist der Fokus des Hauptfensters solange weg, bis ich Enter oder Space drücke (als wäre die Message Box unsichtbar, aber trotzdem vorhanden). Wenn ich allerdings DefWindowProc ganz am Ende immer als Rückgabewert übergebe, egal, welche Nachricht verarbeitet wurde, funktioniert alles, wie es soll.
Kann ich nicht nachvollziehen! Bei mir kommt sauber eine MessageBox allerdings habe ich den WM_PAINT Handler einfach rausgenommen!
-
Ich sagte ja auch: Ohne WM_PAINT funktioniert es. Doch ich habe das Problem bereits gefunden: Ich habe im WM_PAINT-Zweig kein BeginPaint und EndPaint aufgerufen.
-
@Martin Richter: Doppelposts sind schon sinnvoll, jo, stimmt!
Martin Richter schrieb:
Kann ich nicht nachvollziehen! Bei mir kommt sauber eine MessageBox allerdings habe ich den WM_PAINT Handler einfach rausgenommen!
OMG das hab ich doch da oben geschrieben...das IST die Lösung seines Problems. Siehe hier:
CodeFinder schrieb:
// Entweder du fängst die Nachricht ab und zeichnest was oder du lässt es^^

Martin Richter schrieb:
Es würde keinen korrekten Cleanup geben.
Doch gibt es, da das Fenster später automatisch geschlossen (
korrekt abgebaut) wird. Aber NES-Spieler's Lösung fruchtet natürlich auch
. Man muss sich halt nur manuell um das restliche CleanUp kümmern. Aber das variiert ja von Programm zu Programm, logisch.Martin Richter schrieb:
Außerdem haben diese beiden Nachrichten nichts mit dem geschliederten Problem zu tun.
Hm glaube du warst auch der einzige der das vermutet hat.

PS, @NES-Spieler:
CodeFinder schrieb:
// nur ein DestroyWindow zerstört das fenster und die Anwendung läuft weiter, was haste davon ?^^

NES-Spieler schrieb:
Die WM_CLOSE-Nachricht ruft ja die WM_DESTROY-Nachricht durch die Funktion DestroyWindow auf
Jo my fault, ich wusste nicht das die Nachricht an WM_DESTROY mittels DestroyWindow weitergereicht wird. -Sorry-
