[GoCODE]SendMessage[GELÖST] Neues Topic: Perfektes Beenden
-
Es ist eine Unsitte!
Wieder mal was für mein Blog.WM_DESTROY ist eine interne Nachricht, die durch DestroyWindow ausgelöst wird.
Auch hier hast Du nichts mit zu tun...Wenn Du schon PostMessage verwendest und ein Handle hast, müsstest Du auch wissen, das man das Handle mit DestroyWindow benutzen könnte...
Verwende die entsprechenden API-Funktionen und die Nachricht wird vom OS versendet.
BTW:
1. Es ist unüblich Personen in einem Forum direkt anzusprechen.
2. Warum sollte ich mich besonders damit auskenne? Es gibt andere, dies es auch können?
3. Wenn Du kein SDK da hast oder keine GUI, aber hier Posten kannst, dann kannst Du auch die Doku zu DestroyWindow ergoogeln, oder?
-
Martin Richter schrieb:
Es ist eine Unsitte!
<Loriot>Ach was?</Loriot>
Es gibt also keine saubere Möglichkeit, Fenster aus anderen Threads zu schließen (DestroyWindow funktioniert hier bekannterweise nicht)? Und wenn die Microsofties das machen, dann machen sie was falsch (z.B. im Artikel How To Terminate an Application "Cleanly" in Win32)?
-
Gästchen schrieb:
Martin Richter schrieb:
Es ist eine Unsitte!
<Loriot>Ach was?</Loriot>
Es gibt also keine saubere Möglichkeit, Fenster aus anderen Threads zu schließen (DestroyWindow funktioniert hier bekannterweise nicht)? Und wenn die Microsofties das machen, dann machen sie was falsch (z.B. im Artikel How To Terminate an Application "Cleanly" in Win32)?Rembrand? Bahnhof?
In diesem Artikel wird WM_CLOSE versendet und nicht WM_DESTROY.Nein! Man kann nicht durch versenden von WM_DESTROY erreichen was WM_DESTROY tut.
Es gibt sicherlich saubere Lösungen ein Fenster aus einem anderen Thread zu zerstören! Logo.
Definiere eine eigene Nachricht. Sende diese an das Fenster. Baue einen Handler für dieses Fenster und diese Nachricht, oderdas Parent, der dann in dem Eigentümerthread des Fensters DestroyWindow aufruft...Die Doku ist eindeutig:
http://msdn2.microsoft.com/en-us/library/ms632682.aspxA thread cannot use DestroyWindow to destroy a window created by a different thread.
-
Der "Default-Handler (DefWindowProc)" für WM_CLOSE ruft DestroyWindow () auf.
Wenn man somit in der WM_CLOSE DestroyWindow () selbst aufruft, dann wird DestroyWindow () praktisch zweimal aufgerufen.
-
draufleger schrieb:
Der "Default-Handler (DefWindowProc)" für WM_CLOSE ruft DestroyWindow () auf.
Wenn man somit in der WM_CLOSE DestroyWindow () selbst aufruft, dann wird DestroyWindow () praktisch zweimal aufgerufen.Nicht ganz richtig. Wenn man selber in WM_CLOSE DestroyWindow aufruft dann returniert man natürlich und ruft nicht DefWindowProc auf... oder?
So sollte man sich verhalten, wenn man es gemäß Doku macht. :xmas1:
-
Martin Richter schrieb:
In diesem Artikel wird WM_CLOSE versendet und nicht WM_DESTROY.
Au weia, da hast Du natürlich recht, da habe ich mich aber mächtig verhauen. Ich würde jetzt gern noch etwas schlaues sagen, aber wenn man so daneben liegt...
-
2. Warum sollte ich mich besonders damit auskenne? Es gibt andere, dies es auch können?
Du bist doch der Don Quichotte.(dein Blog)
Das beantwortet auch die Frage warum ich dich direkt angesprochen habe.Das 'HWND hButton' am Ende Deiner WndProc stellt übrigens einen Fehler gegen die vorgeschriebene Syntax einer Fensterprozedur da. Das muss da weg - also hier: C/C++ Code:
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,HWND hButton)Keine Ahnung wie das da reingekommen ist.
Es ist eine Unsitte! Wieder mal was für mein Blog.
Das mit dem bool running auch? Das habe ich aus einem Tutorial.(Spieleprogrammierung)

Ahoi, also falls *ich* Dir nicht antworten soll, kannst Du meinen Post ja einfach ignorieren (da ich Dich ja angeblich mobbe) , alle anderen können ihn einfach als Antwort auf seine Frage verstehen .
Zu Deiner Frage: Deine 'Konstruktion' ist überflüssig, da ein Aufruf von PostQuitMessage (wie der Name auch schon sagt) eben ein WM_QUIT in Deine Nachrichtenschleife einreiht. Falls GetMessage auf ein WM_QUIT trifft, sorgt das für die Rückgabe des Wertes FALSE. Und da while(FALSE) { ... } nicht weiter bearbeitet wird (eben weil das Abbruchkriterium der Schleife erfüllt ist), beendet sich das Programm. DestroyWindow sollte ebenfalls aufgerufen werden, da es Aufräumarbeiten durchführt (z.B. das Löschen von Timern, die mit dem Fenster assoziiert sind).
Willst du mir damit sagen dass ich bei, ...
case WM_KEYDOWN: if(wParam == 27) //Escape { PostQuitMessage(0) } break;...das hier so machen könnte: (Doppelpunkt kein Punkt. *WICHTIG* )
Wenn Du an irgendeiner Stelle dafür sorgen willst, dass sich Dein Programm beendet, mache ich das immer mit:
SendMessage(hWnd, WM_CLOSE, 0, 0);@Martin Richter: Ist das auch sauber?(oder doch Unsitte
)Nicht ganz richtig. Wenn man selber in WM_CLOSE DestroyWindow aufruft dann returniert man natürlich und ruft nicht DefWindowProc auf... oder?
So sollte man sich verhalten, wenn man es gemäß Doku macht.
Besserwisser.
(Ich will nicht bestreiten , das stimme nicht. Es stimmt.)
@Draufleger: Danke das wird mir weiterhelfen. Das bestätigt auch warum man WM_CLOSE senden sollte.Erstmal *DANKE* an alle. Mir scheint es so als würde halb Windows nur aus Befehlen zum Beenden zu bestehen und zeim Aufrümen und zum zerstörem.

P.S.: GoCODE klingt mal derbst beschis*en.( Warum hat das keine gesagt? )
-
Martin Richter schrieb:
Wenn man selber in WM_CLOSE DestroyWindow aufruft dann returniert man natürlich und ruft nicht DefWindowProc auf... oder?
Wo bleibt dann das Zusammenspiel mit dem Betriebssystem ?
-
Man kann doch nicht einfach sein Fenster zerstören und dem OS mitteilen, daß WM_CLOSE abgebrochen wurde !
-
Auch wenn das in sehr vielen Dokus favorisiert wird.

-
Korrekt beendet wird mit der DefWindowProc der WM_CLOSE (mit einem PostQuitMessage () in der WM_DESTROY oder WM_NCDESTROY).
-
Sorry, Spamfilter !

-
Wenn Du Dein Programm beenden möchtest, das ein fenster hat, dan:
1. Zerstöre das Main Window mit DestroyWindow (oder sende WM_CLOSE wenn es sein muss).
2. Im WM_DESTROY Handler platziere ein PostQuitMessage.PostQuitMessage sollte nur im Response auf die Zerstörung des Main Windows gesendet werden....
Selbst wenn ich in manchen Fällen "Don Quichote" bin, gibt es genug andere die richtige Antworten geben können. Also stelle lieber allgemein eine Frage zur Diskussion...
-
Martin Richter schrieb:
Selbst wenn ich in manchen Fällen "Don Quichote" bin, gibt es genug andere die richtige Antworten geben können. Also stelle lieber allgemein eine Frage zur Diskussion...
Habe ich gemacht.
Zusammenfassend ist zu sagen: Wenn ich mein Programm von einer beliebigen Stelle des Programmmes beenden möchte z.B.: Per Escapetastendruck dann schaut meine Window Procedure wie folgt aus:LRESULT CALLBACK WindowProcedure(HWND hWindow,HINSTANCE hInstance,WPARAM wParam,LPARAM lParam,unsigned int message) { switch(message) { case WM_KEYDOWN: DestroyWindow(hWindow) break; case WM_DESTROY: PostQuitMessage(wParam); // Das Programm wird mit der gedrückten Taste beendet // bzw um korrekt zu sein: Der virtuelle // Tastencode der gedrückten Taste wird als // Exitcode verwendet. Zufrieden? break; } }Richtig so?(Und ja ich weis das man jede andere Botschaft an Windows via DefWindowProc weiterleiten muss.
)
-
Ja, kannst Du so machen (Dir ist aber schon klar, das bei dem Code, Dein Fenster bei jeder Taste beendet wird, oder? Nicht nur bei Escape
.).Hoffe, Du hälst mich für kompetent genug
... falls nicht frag am besten nochmal Martin, oder er bescheinigt mir ausreichende Kompetenzen zur Beantwortung Deiner Fragen
- dann kannst Du Dir auch ganz sicher sein *grinz*.PS: Das, im Aufruf von PostQuitMessage, angegebene 'wParam' als Parameter ist falsch, siehe: http://msdn2.microsoft.com/en-us/library/ms632620.aspx

MSDN zu WM_DESTROY schrieb:
Parameters:
- wParam: This parameter is not used.

- lParam: This parameter is not used.
EDIT: Das ist jawohl n Witz oder:
C-Chris schrieb:
LRESULT CALLBACK WindowProcedure(HWND hWindow,HINSTANCE hInstance,WPARAM wParam,LPARAM lParam,unsigned int message)Dazu sag ich jetzt mal nix...

- wParam: This parameter is not used.
-
CodeFinder schrieb:
Ja, kannst Du so machen (Dir ist aber schon klar, das bei dem Code, Dein Fenster bei jeder Taste beendet wird, oder? Nicht nur bei Escape
.).Hoffe, Du hälst mich für kompetent genug
... falls nicht frag am besten nochmal Martin, oder er bescheinigt mir ausreichende Kompetenzen zur Beantwortung Deiner Fragen
- dann kannst Du Dir auch ganz sicher sein *grinz*.PS: Das, im Aufruf von PostQuitMessage, angegebene 'wParam' als Parameter ist falsch, siehe: http://msdn2.microsoft.com/en-us/library/ms632620.aspx

MSDN zu WM_DESTROY schrieb:
Parameters:
- wParam: This parameter is not used.

- lParam: This parameter is not used.
EDIT: Das ist jawohl n Witz oder:
C-Chris schrieb:
LRESULT CALLBACK WindowProcedure(HWND hWindow,HINSTANCE hInstance,WPARAM wParam,LPARAM lParam,unsigned int message)Dazu sag ich jetzt mal nix...

*LOL* einmal habe ich sowas von RECHT. Ich sage nur "this Parameter is not used" . Den Parameter übergebe ich und er ist von WM_KEYDOWN benützt. Er übergibt nähmlich den Virtuellen Tastencode der gedrückten Taste und ja mir ist schon klar, dass ich bei jeder Taste das Programm beende. Wie kommst du darauf: wParam von "WM_DESTROY"?!(Davon ist hier garnicht die Rede
) Und was gibt es an meiner WindowProcedure zu meckern :p
EDIT: Ich sollte vielleicht noch schreiben, dass ich das wParam das durch einen Tastendruck in "g_wLastKeyDownParam" speichere.
Würde dann in etwas so aussehen://Global: WPARAM g_wLastKeyDownParam; //WindowProc: case WM_KEYDOWN: g_wLastKeyDownParam = wParam; SendMessage(hWindow,WM_DESTROY,NULL,NULL); break; case WM_DESTROY: PostQuitMessage(g_wLastKeyDownParam); break;Das hier war nur zur Vollständigkeit. Damit auch CodeFiner es versteht

Und CodeFinder was sagst du nun? Ach ja und vielleicht muss ich den wParam Datentyp noch in einen Integer umwandeln(Für PostQuitMessage). Ich habe kein SDK da um das auszuprobieren. Wahrscheinlich ist WPARAM nur ein typedef...habe da aber keine Ahnung
Es wäre nett wenn du schreibst: "Ja stimmt! ".
- wParam: This parameter is not used.
-
C-Chris schrieb:
Und was gibt es an meiner WindowProcedure zu meckern :p
Sie ist falsch.
C-Chris schrieb:
Wie kommst du darauf: wParam von "WM_DESTROY"?!(Davon ist hier garnicht die Rede
)Tja, Eigentor. Doch davon ist die Rede, vergleiche mal Deinen eigenen (von Dir geposteten) Code:
C-Chris schrieb:
LRESULT CALLBACK WindowProcedure(HWND hWindow,HINSTANCE hInstance,WPARAM wParam,LPARAM lParam,unsigned int message) { switch(message) { case WM_KEYDOWN: DestroyWindow(hWindow) break; case WM_DESTROY: PostQuitMessage(wParam); // Das Programm wird mit der gedrückten Taste beendet // bzw um korrekt zu sein: Der virtuelle // Tastencode der gedrückten Taste wird als // Exitcode verwendet. Zufrieden? break; } }Das wParam *muss* also in Bezug von WM_DESTROY verwendet worden sein, da ist nur als Parameter Deine WndProc definiert ist, sonst nicht. Hättest Du hier direkt Dein 'g_wLastKeyDownParam' eingefügt, wäre die Sache klar gewesen.
C-Chris schrieb:
case WM_KEYDOWN: g_wLastKeyDownParam = wParam; SendMessage(hWindow,WM_DESTROY,NULL,NULL); break;Uff, sagmal, hast Du Dir durchgelesen, was Martin Dir erklärt hat?!

C-Chris schrieb:
Es wäre nett wenn du schreibst: "Ja stimmt! ".
Würde ich gerne...
-
Oh mein Gott.

Dann eben://Global: WPARAM g_wPrevParam; //WndProc: case WM_KEYDOWN: DestroyWindow(hWindow); g_wPrevParam = wParam; break; case WM_DESTROY: PostQuitMessage(g_wPrevParam); break;So richtig? Noch was? Was gibst an meiner WndProc auszusetzen?
-
Deine "WndProc" (als __stdcall) mit -5- Parametern entfernt immer -5- Parameter kurz vor Funktionsende vom Stack.
Das Betriebssystem ruft sie aber mit nur -4- Parametern auf.
Früher oder später verursacht die "WndProc" mit -5- Parametern einen fetten Stackfault.
-
So sieht der Prototyp einer Fensterprozedur aus:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);Und nicht anders.