PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : win32 - window messages


Che
2003-06-22, 10:30:03
Hola,

Wie üblich fange ich in der MessageLoop alles was da so hereinkommt mit Peekmessage() ab, um bei WM_CLOSE das Programm zu beenden. Das Problem: Ich bekomme nie ein WM_CLOSE! In der MessageLoop, wohlgemerkt. Die WindowProcedure empfängt das WM_CLOSE, kein Problem.

Zuerst dachte ich vielleicht ist das WindowHandle mit dem ich Peekmessage aufrufe irgendwie falsch, aber das kann ich ausschließen, denn: alle anderen Messages kann ich mit PeekMessage abfangen!

PeekMessage(&WndMsg, WindowSystem.getWindowHandle(), 0, 0, PM_REMOVE);

if(WndMsg.message == WM_LBUTTONDOWN) //das geht, programm wird beendet!
{
ExitProgram =true;
MessageBox(NULL,"exit main loop, lbuttondown","i",MB_OK);
}

if(WndMsg.message == WM_KEYDOWN && WndMsg.wParam == VK_ESCAPE) //das geht auch!
{
MessageBox(NULL,"exit main loop, escape","i",MB_OK);
ExitProgram = true;
}

if(WndMsg.message == WM_CLOSE) //Hier komme ich nie hin!!!
{
MessageBox(NULL,"exit main loop, close","i",MB_OK);
ExitProgram = true;
}

else
{
//Weiter an die WindowProcedure
TranslateMessage(&WndMsg);
DispatchMessage(&WndMsg);
}


In der WindowProcedure prüfe ich dann nocheinmal auf WM_CLOSE, und da krieg ichs. ???
In der WinProc ist die message da, in der MessageLoop nicht? I'm confused...???

Demirug
2003-06-22, 11:03:58
Benutzt du ALT+F4 oder das Systemmenü unter dem Fenstericon zum schliessen des Fensters?

Falls ja ist das die Erklärung. In beiden Fällen wird ein Systemcomando geschickt welches erst durch TranslateMessage zu WM_CLOSE wird.

Alles in allem sollte man aber so auch keine Applikation beenden. Der Messageloop sollte die Applikation nur beenden wenn eine WM_QUIT Message emfangen wird. Alle anderen Nachrichten die zum Benden der Applikation führen können sollten von den entsprechenden Messagefunktionen bearbeitet werden und mit PostQuitMessage eine WM_QUIT Message im queue plazieren. Das gibt allen Nachrichten die noch in der queue sind die Möglichkeit noch abgearbeitet zu werden.

Che
2003-06-22, 11:38:33
Original geschrieben von Demirug
Benutzt du ALT+F4 oder das Systemmenü unter dem Fenstericon zum schliessen des Fensters?

Falls ja ist das die Erklärung. In beiden Fällen wird ein Systemcomando geschickt welches erst durch TranslateMessage zu WM_CLOSE wird.

Alles in allem sollte man aber so auch keine Applikation beenden. Der Messageloop sollte die Applikation nur beenden wenn eine WM_QUIT Message emfangen wird. Alle anderen Nachrichten die zum Benden der Applikation führen können sollten von den entsprechenden Messagefunktionen bearbeitet werden und mit PostQuitMessage eine WM_QUIT Message im queue plazieren. Das gibt allen Nachrichten die noch in der queue sind die Möglichkeit noch abgearbeitet zu werden.

Ich habe Abfragen für quit, close und was es da sonst noch gibt jeweils in der MessageLoop und in der Winproc: in der Messageloop empfange ich nie etwas, in der winproc alles (bis auf quit, das ja nur von peek- oder getmessage aufgefangen wird, bei mir nicht einmal von diesen)

Zum beenden habe ich getestet: das X rechts, Alt-F4, "Beenden" im Menü. Alle drei senden Close, was ich aber NUR in der Winproc empfangen kann. (Ein TranslateMessage vor Peek hat da nix geändert.)

Was mich wundert ist dass ich offenbar nur Messages die mit dem beenden zu tun haben nicht bekomme, Escape un Maus (s. Codeschnipsel oben) funktionieren wunderbar.

Wenn die Sache funktioniert wird natürlich nur bei Quit beendet, der Codeschnipsel sieht ja nur deshalb so aus weil ich in meiner Verzweiflung schon alles nur denkbare ausprobiert habe. (Normalerweise werden ja auch keine Keystates im Messageloop bearbeitet...) Trotzdem danke für den Hinweis :)

Che
2003-06-22, 20:51:49
Ich habe eine Abfrage eingefügt:

bool test = PeekMessage(&WndMsg, WindowSystem.getWindowHandle(), 0, 0, PM_REMOVE);
if(test)
MessageBox(NULL,"peek-ja","i",MB_OK);
else
MessageBox(NULL,"peek-nein","i",MB_OK);

um zu sehen ob Peek überhaupt etwas empfängt.

Mit dieser Abfrage funktioniert alles: Ich klicke aufs X, die Winproc empfängt wm_close und postet daraufhin die quitmessage, Peek empfängt die Quitmessage, das Programm wird beendet.

Ich entferne die Abfrage, klicke aufs X, die Winproc empfängt wm_close und postet daraufhin die quitmessage, Peek empfangt die Quitmessage nicht, das programm wird nicht beendet.

Das ganze verwirrt mich schön langsam...???

Che
2003-06-23, 19:06:45
Ich weiß einfach nicht mehr weiter. Ich habe meinen Code x mal durchgesehen aber ich finde weder einen logischen Fehler noch sonstwas. Es kann natürlich sein dass ich schon so fixiert bin auf dieses Problem dass ich irgendetwas anderes ganz einfaches übersehen habe, deshalb poste ich einfach mal meinen Code:

//----------------------MessageLoop in WinMain
while (!ExitProgram)
{
PeekMessage(&WndMsg, WindowSystem.getWindowHandle(), 0, 0, PM_REMOVE);

TranslateMessage(&WndMsg);

if(WM_QUIT == WndMsg.message)
{
MessageBox(NULL,"exit main loop, quit","i",MB_OK);
ExitProgram = true;
}
if(WM_KEYDOWN == WndMsg.message && VK_ESCAPE == WndMsg.wParam)
{
MessageBox(NULL,"exit main loop escape","i",MB_OK);
ExitProgram = true;;
}

else
{
//Weiter an die WindowProcedure
TranslateMessage(&WndMsg);
DispatchMessage(&WndMsg);
}
}

MessageBox(NULL,"windosystem->shutdown","i",MB_OK);
WindowSystem.Shutdown();

return (WndMsg.wParam);




//-------------------------WindowProcedure
switch (uMsg)
{
case WM_DESTROY:
{
MessageBox(NULL,"wm_destroy empfangen","i",MB_OK);
break;
}
case WM_CLOSE:
{
MessageBox(NULL,"wm_close empfangen, postquit","i",MB_OK);
PostQuitMessage(0);
break;
}
case WM_CREATE:
{
MessageBox(NULL,"wm_create empfangen","i",MB_OK);
break;
}
case WM_SIZE:
{
MessageBox(NULL,"wmsize empfangen","i",MB_OK);
break;
}
default:
//an Windows weitergeben
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;


Ich hoffe ihr könnt mir helfen: Alles funktioniert wuderbar bis aufs beenden, da empfange ich WM_CLOSE in der WinProc, poste die Quitmessage

die NIE in der MessageLoop ankommt,

sodass das Programm nicht beendet werden kann. Mit Escape funktionierts. ???
??? Ich versteh das nicht :cryl:

stabilo_boss13
2003-06-23, 19:57:28
Du solltest den Rückgabewert von PeekMessage auswerten.

Schreib doch mal versuchsweise

if (PeekMessage(&WndMsg, WindowSystem.getWindowHandle(), 0, 0, PM_REMOVE))
{
if(WM_QUIT == WndMsg.message)
{
MessageBox(NULL,"exit main loop, quit","i",MB_OK);
ExitProgram = true;
}
...
}

Gast
2003-06-23, 20:08:45
Original geschrieben von stabilo_boss13
Du solltest den Rückgabewert von PeekMessage auswerten.

Schreib doch mal versuchsweise

...



Nützt nix. Aber wenn ich

if(PeekMessage(&WndMsg, WindowSystem.getWindowHandle(), 0, 0, PM_REMOVE))
MessageBox(NULL,"ja","i",MB_OK);
else
MessageBox(NULL,"nein","i",MB_OK);
schreib dann gehts. Aber eine Applikation bei der man ständig Message Boxes wegklicken muss ist auch nix gscheits...;)

Peek Message empfängt also schon, da hat alles seine Richtigkeit. Aber wenn ich auf WM_QUIT hin überprüfe wird das ganze rätselhaft...Ich hab echt keine Ahnung was da danebengeht.

Übrigns hab ich GetMessage() auch probiert, das sollte ja 0 zurückgeben wenn WM_QUIT empfangen wird, Betonung auf SOLLTE...

Che
2003-06-23, 20:10:38
^^
Ich war das

Che
2003-06-24, 20:13:11
Wer denkt denn schon an sowas: :|

PeekMessage(&WndMsg, NULL, 0, 0, PM_REMOVE);


Mit diesem Code funktioniert alles wies sollte.

Und jetzt noch einmal für alle: Windoof, Micro$oft, 1, 2, 3, die ganze Litanei... ?-)

Für Erklärungsversuche bin ich dankbar.

MfG

Xmas
2003-06-24, 20:22:41
Original geschrieben von Che
Für Erklärungsversuche bin ich dankbar.

MfG
Erklärungsversuche... nun, gibst du dort ein Handle an bekommst du nur die Nachrichten für ein bestimmtes Fenster. WM_QUIT ist aber keine Nachricht an ein Fenster, sondern an den Thread. Schließlich soll nicht ein Fenster geschlossen werden (dafür ist WM_CLOSE da), sondern die Applikation beendet.

Che
2003-06-24, 20:31:06
Original geschrieben von Xmas
Erklärungsversuche... nun, gibst du dort ein Handle an bekommst du nur die Nachrichten für ein bestimmtes Fenster. WM_QUIT ist aber keine Nachricht an ein Fenster, sondern an den Thread. Schließlich soll nicht ein Fenster geschlossen werden (dafür ist WM_CLOSE da), sondern die Applikation beendet.
Auszug MSDN:

Note that PeekMessage always retrieves WM_QUIT messages, no matter which values you specify for wMsgFilterMin and wMsgFilterMax.

Dein Erklärungsversuch dürfte allerdings mehr sein als nur ein Versuch ;)
Bevor WM_QUIT gesendet wird, wird die Message Queue für das Fenster aufgelöst...Wenn man nun bei Peekmessage ein Window Handle angibt kann dort ja nix mehr gefunden werden, weil die Message Queue ja nimmer exisitiert.

Che
2003-06-24, 20:32:33
p.s: Der Kandidat hat 100 Punkte! Glückwunsch Xmas :)

Xmas
2003-06-24, 20:35:27
Original geschrieben von Che
Auszug MSDN:

Note that PeekMessage always retrieves WM_QUIT messages, no matter which values you specify for wMsgFilterMin and wMsgFilterMax.
wMsgFilterMin und wMsgFilterMax sind aber der dritte bzw. vierte Parameter, nicht der zweite. ;)

Che
2003-06-24, 20:39:16
Ja klar, ich bezog mich auch eher auf das always...

Allerdings merke ich gerade dass ich das aus dem falschen Zusammenhang gerissen habe. Ich dachte alwys im Sinne von "sowieso und überhaupt immer", aber gemeint ist wohl eher "immer, egal was bei wMsgFilterMin und Max definiert wird." ?-)

DiceZ
2006-05-20, 17:44:07
Hi!

Ich erlaube mir mal den Thread wieder auszubuddeln.

Hab' ein Programm geschrieben in dem eine längere Schleife abgearbeitet werden muß.

In dieser Schleife ist eine ne Message-Loop (nach einem Beispiel im Internet) eingebaut. Die soll "Keine Rückmeldung" verhindern und außerdem soll ein Fortschrittsbalken das tun was die eben normalerweise tun... (ohne Message-Loop läuft der Balken nicht durch)

Wenn ich während der Schleifenbearbeitung einfach das Programm schließe (mit dem X), verschwindet zwar das Fenster, aber die Schleife wird aus irgendeinem Grund noch weiter bearbeitet...

Hab die Vermutung das das irgendwie ein ähnliches Problem ist.
Hoffe ihr wisst wie das gemeint ist und habt nen guten Tipp für mich...

Danke schonmal


MfG DiceZ

Gast
2006-05-20, 17:49:33
Bau ein, dass im Falle von WM_DESTROY ein Wert nun FALSE ist, damit die Schleife beendet wird (wenn es eine while(X)-Schleife ist).

DiceZ
2006-05-20, 18:01:34
Sie sieht zur Zeit so aus ( nicht mehr wie im Beispiel welches ich gefunden habe, weil ich selber auch schon ein wenig probiert habe)

MSG msg;
while (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE) && msg.message!=WM_DESTROY)
{
::AfxGetThread()->PumpMessage();
}

Leider zeigt das Programm immer noch das beschriebene Verhalten... und ich bin jetzt auch nich so die Leuchte was MFC und Windows Nachrichten angeht..

Expandable
2006-05-20, 18:23:42
Bist Du Dir sicher, dass du PM_NOREMOVE brauchst?

DiceZ
2006-05-20, 18:44:11
Expandable[/POST]']Bist Du Dir sicher, dass du PM_NOREMOVE brauchst?

Nein bin ich nicht, wie gesagt bin mit solchen Sachen nicht gerade vertraut.

Wenn ich aber PM_REMOVE einbau wirkt das irgendwie zäh und schliessen kann ich's während der Schleifenbearbeitung auch nicht mehr.


edit: Die dort beschriebene hab' ich verwendet.

http://www.mpdvc.de/html.htm#Q75