[GoCODE]SendMessage[GELÖST] Neues Topic: Perfektes Beenden
-
Auflösung des Threads:
Die Lösung dieses Threads gibt es auf dieser Seite:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-200760-and-start-is-20-and-sid-is-393a4dbe01a3d7a6a7755ab5100f4df1.html
Ihr müsst allerdings nach ganz unten scrollen. Es ist der Post: [CLOSED]Endgültige Lösung
Viel Spass beim perfekten BeendenUrsprünglischer Post:
Guten Tag erstmal,
Was haltet ihr davon:LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,HWND hButton) { switch(msg) { case WM_KEYDOWN: if (wParam == VK_ESCAPE) { PostMessage(hWnd,WM_DESTROY,NULL,NULL) //oder so ähnlich } break; case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; }Ich hätte gerne ein Kommentar dazu. Ich hoffe dies ist keine "Unsitte". Falls schon bitte ich um Verbesserungsvorschläge.
Einen anderen Vorschlag hätte ich auch noch://Global: bool running = true; //in WinMain() {} while (running && GetMessage(&msg,NULL,0,0) { TranslateMessage(&msg); DispatchMessage(&msg); } //WndProc if(msg->wParam == VK_ESCAPE) { running = false;}
Welche der beiden Methoden findet ihr effizienter bzw. professioneller. Was ist performanter? Danke an alle!
P.S.: GoCODE = guter Code
bedeutet soviel wie effizienter,sauberer CodeEDIT:
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...
Ich habe den Beitrag deinen Wünschen gemäss editiert.[u]
-
du bist irgendwie komisch

-
DestroyWindow
-
bool runningist quatsch
dein programm wird schon merken, wenn es keine nachrichten mehr mit GetMessage bekommt - dann wurde nämlich bereits WM_QUIT gesendet
-
oO schrieb:
du bist irgendwie komisch

Wieso? Warum? Weshalb?
-
hey schrieb:
bool runningist quatsch
dein programm wird schon merken, wenn es keine nachrichten mehr mit GetMessage bekommt - dann wurde nämlich bereits WM_QUIT gesendet
Und woher sollte WM_QUIT gesendet werden?
P-Poss schrieb:
DestroyWindow
Wie wende ich das an? Welche Parameter? Ich habe zur Zeit keine GUI bzw. WinSDK da.
-
Ahoi, also falls *ich* Dir nicht antworten soll, kannst Du meinen Post ja einfach ignorieren (da ich Dich ja angeblich mobbe) :p , 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).Das 'HWND hButton' am Ende Deiner WndProc stellt übrigens einen Fehler gegen die vorgeschriebene Syntax einer Fensterprozedur da. Das muss da weg
- also hier:LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,HWND hButton)Dann vllt noch dazu:
PostMessage(hWnd,WM_DESTROY,NULL,NULL) //oder so ähnlichWenn Du an irgendeiner Stelle dafür sorgen willst, dass sich Dein Programm beendet, mache ich das immer mit:
SendMessage(hWnd, WM_CLOSE, 0, 0);Unter WM_CLOSE führe ich dann Aufräumarbeiten durch, vorher ggfs. die Frage an den Benutzer, ob er das Programm wirklich beenden will, und schließlich folgt der Aufruf von DestroyWindow. Also beispielsweise so:
// ... case WM_CLOSE: if(MessageBox(hWnd, TEXT("Wollten Sie das Programm wirklich beenden?"), TEXT("Wirklich beenden?"), MB_YESNO | MB_ICONINFORMATION) == IDNO) break; // Hier ggfs. Clean-Up: [...] DestroyWindow(hWnd); break; // ...Der Vorteil ist, dass Aktionen, die immer vor dem Beenden des Programms durchgeführt werden müssen/sollten (-> Clean-Up), immer zentral an einer Stelle codiert werden können (eben unter WM_CLOSE).
PS: Es wäre sinnvoll, wenn Du zusätzlich noch posten könntest, was Du erreichen willst, dass muss man sich nämlich erstmal aus Deinem Code ableiten, was ja nicht zwangsläufig erfolgreich sein muss
.
-
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.
)