[C++] WinApi: ClassName (?)
[C++] WinApi: ClassName (?)
Hallo,
ich stand vor kurzem vor einem Problem.
Ich habe ein Programm geschrieben, welches bei ankommenden Netzwerksignalen (Das war diese Frage) eine "selbst-gemalte" MessageBox anzeigt. Ist im Prinzip ein Fenster ohne Rahmen und ein kleiner Haken drinnen.
Ich habe dieses Fenster mittels CreateWindowEx kreiert. Das klappte auch soweit ganz gut.
ABER: es klappte nur ein einziges mal!!! Beim 2ten Aufruf von CreateWindowEx mit GENAU DENSELBEN Parametern wurde das Programm einfach beendet.
Ich bekam irgendwann heraus, dass ich niemals das Fenster gleich nennen durfte. Also habe ich die Parameter lpClassName und lpWindowName bei jedem Aufruf verändert, sowie auch der Parameter lpszClassName der Struktur WNDCLASSW die ja bei der Funktion RegisterClass verwendet wird.
Jetzt ist meine Frage: WIESO?
Ich habe ja auch nach jedem Aufruf der MessageBox ordentlich UnregisterClass aufgerufen... :?:
Ich meine, es funktioniert jetzt, aber es scheint mir keine sauberen Lösung zu sein.
Ich wollte nur mal wissen, was ich da falsch gemacht habe...
ich stand vor kurzem vor einem Problem.
Ich habe ein Programm geschrieben, welches bei ankommenden Netzwerksignalen (Das war diese Frage) eine "selbst-gemalte" MessageBox anzeigt. Ist im Prinzip ein Fenster ohne Rahmen und ein kleiner Haken drinnen.
Ich habe dieses Fenster mittels CreateWindowEx kreiert. Das klappte auch soweit ganz gut.
ABER: es klappte nur ein einziges mal!!! Beim 2ten Aufruf von CreateWindowEx mit GENAU DENSELBEN Parametern wurde das Programm einfach beendet.
Ich bekam irgendwann heraus, dass ich niemals das Fenster gleich nennen durfte. Also habe ich die Parameter lpClassName und lpWindowName bei jedem Aufruf verändert, sowie auch der Parameter lpszClassName der Struktur WNDCLASSW die ja bei der Funktion RegisterClass verwendet wird.
Jetzt ist meine Frage: WIESO?
Ich habe ja auch nach jedem Aufruf der MessageBox ordentlich UnregisterClass aufgerufen... :?:
Ich meine, es funktioniert jetzt, aber es scheint mir keine sauberen Lösung zu sein.
Ich wollte nur mal wissen, was ich da falsch gemacht habe...
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] WinApi: ClassName (?)
Ich weiß nicht, was da schief läuft, aber ich glaube auch nicht, dass das Programm „einfach beendet“ wurde. Die WinAPI ruft niemals TerminateProcess() auf, wenn was nicht klappt, sondern löst immer irgendeine Exception aus, und falls die nicht gefangen wird, wird das Programm der Fehlerberichterstattung übergeben. Gab es keine Debug-Ausgaben? Keine Haltepunkte? Keinen Crash Dump?
Das mit der Fensterklasse stinkt mir aber. Die solltest du keinesfalls direkt um die Message Box bauen.
Fensterklassen sind da, damit fremde UI deine Fenster benutzen kann. Beispiel: Alle Edit-Controls, Combo-Boxen usw. in Windows liegen in der Bibliothek CommCtrl32.dll.
Das mit der Fensterklasse stinkt mir aber. Die solltest du keinesfalls direkt um die Message Box bauen.
Fensterklassen sind da, damit fremde UI deine Fenster benutzen kann. Beispiel: Alle Edit-Controls, Combo-Boxen usw. in Windows liegen in der Bibliothek CommCtrl32.dll.
- jedes Windows-Programm, das eine Combo-Box nutzt, lädt CommCtrl32.dll
- CommCtrl32.dll registriert die Combo-Box-Klasse unter dem Namen COMBOBOX
- das Programm ruft CreateWindow() mit COMBOBOX auf
- jetzt hat es eine Combo-Box und musste dazu nichts wissen außer dem Namen
- wenn das Programm beendet, zerstört es die Combo-Box
- CommCtrl32.dll wird entladen
- dabei zieht es die Klassenregistrierung zurück
Re: [C++] WinApi: ClassName (?)
Es gab keine Exception, keine Debugausgabe, kein Crash dump, garnix. Ich habe den Haltepunkt auf der Zeile von CreateWindowEx(...) gesetzt, programm hielt dort, beim Ausführen dieser Zeile beendete sich der Debugger einfach...
Aber okay, das hatte ich garnicht mehr auf den Schirm, dass man CreateWindow zB auch mit COMBOBOX aufrufen kann.
Kann ich ja mal probieren.
Aber wie gesagt: komisch ist das Verhalten schon...
Aber okay, das hatte ich garnicht mehr auf den Schirm, dass man CreateWindow zB auch mit COMBOBOX aufrufen kann.
Kann ich ja mal probieren.
Aber wie gesagt: komisch ist das Verhalten schon...
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] WinApi: ClassName (?)
Clowns sind komisch; das Verhalten ist sonderbar :)
Dann beendet nicht CreateWindowEx() das Programm, sondern deine Fensterprozedur (die wird innerhalb CreateWindowEx() ja mit WM_CREATE usw. aufgerufen).
Benutzt du assert()? Das löst eine Message Box aus, falls irgendwo was fehlschlägt. Die Message Box kann aber nicht erzeugt werden, während CreateWindowEx() läuft, oder verhakt sich da gern in Endlosschleifen. Dann ruft assert() std::unexpected() oder irgend so einen Scheiß auf.
Setz vor dem Aufruf von CreateWindowEx() einen Haltepunkt in deiner Fensterprozedur und schau, ob der angesprungen wird, bevor sich das Programm beendet! Die Art der Nachricht kannst du im Debugger anzeigen, indem du die entsprechende Variable ins Watch-Fenster einträgst und ,wm anhängst.
Dann beendet nicht CreateWindowEx() das Programm, sondern deine Fensterprozedur (die wird innerhalb CreateWindowEx() ja mit WM_CREATE usw. aufgerufen).
Benutzt du assert()? Das löst eine Message Box aus, falls irgendwo was fehlschlägt. Die Message Box kann aber nicht erzeugt werden, während CreateWindowEx() läuft, oder verhakt sich da gern in Endlosschleifen. Dann ruft assert() std::unexpected() oder irgend so einen Scheiß auf.
Setz vor dem Aufruf von CreateWindowEx() einen Haltepunkt in deiner Fensterprozedur und schau, ob der angesprungen wird, bevor sich das Programm beendet! Die Art der Nachricht kannst du im Debugger anzeigen, indem du die entsprechende Variable ins Watch-Fenster einträgst und ,wm anhängst.
Re: [C++] WinApi: ClassName (?)
Also...ich verwende kein assert oder so.
Das Verhalten ist jetzt ein anderes.... :|
Jetzt schlägt der Aufruf RegisterClass fehl wenn ich zwei mal den gleichen Klassenname übergebe.
Auch egal...
Das Verhalten ist jetzt ein anderes.... :|
Jetzt schlägt der Aufruf RegisterClass fehl wenn ich zwei mal den gleichen Klassenname übergebe.
Auch egal...
-
- Establishment
- Beiträge: 237
- Registriert: 04.02.2005, 09:12
- Benutzertext: www.gamedevstudio.com
- Echter Name: Thomas Mittelsdorf
- Wohnort: Meiningen
- Kontaktdaten:
Re: [C++] WinApi: ClassName (?)
Ich hätte auch auf ein assert() getippt. Vielleicht hast du irgendwo vergessen (wo es notwendig ist) die DefWindowProc() aufzurufen. Manchmal wird darin rekursiv wieder eine Methode an den Callback weitergegeben oder irgendwas mit den Rückgabewerten ist nicht korrekt. Am schlüssigsten wäre aber wirklich assert(), aber da du es nicht benutzt....
Edit: Das Fehlschlagen des 2.Erzeugens mit dem selben Namen deutet darauf hin das UnRegisterClass fehl schlägt. Es ist aber keine gute Lösung Register und UnRegister öfter für die selbe Klasse zu machen.
Edit: Das Fehlschlagen des 2.Erzeugens mit dem selben Namen deutet darauf hin das UnRegisterClass fehl schlägt. Es ist aber keine gute Lösung Register und UnRegister öfter für die selbe Klasse zu machen.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] WinApi: ClassName (?)
Verwendest du die STL? Die verwendet nämlich assert()s. Wenn du falsch auf einen std::vector zugreifst oder so, passiert das genauso.joggel hat geschrieben:Also...ich verwende kein assert oder so.
Aktivier doch mal den Application Verifier für deine Anwendung, dann solltest du eine recht aussagekräftige Fehlermeldung bekommen …
Re: [C++] WinApi: ClassName (?)
ja, ich verwende die STL. Aber ich bin mir zu 100% sicher, dass in dem Moment nichts bei der Verwendung schief geht...
Und wie aktiviere ich diesen "Application Verifier"?
Und wie aktiviere ich diesen "Application Verifier"?
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] WinApi: ClassName (?)
Debug-Version deines Programms kompilieren
Start → Programme → Application Verifier (falls dein Programm 32-bittig ist) oder Application Verifier (x64) (falls es 64-bittig ist) → Application Verifier
Im Fenster dann File → Add Application
zur Debug-Version deines Programms navigieren und die auswählen
Häkchen bei
nun dein Programm im Debugger laufen lassen
im Output-Fenster sollte eine der ersten Meldungen (zwischen Dutzenden foo.dll loaded) sowas sein wie AV Debug Heap enabled; daran siehst du, dass der Verifier mitläuft
Start → Programme → Application Verifier (falls dein Programm 32-bittig ist) oder Application Verifier (x64) (falls es 64-bittig ist) → Application Verifier
Im Fenster dann File → Add Application
zur Debug-Version deines Programms navigieren und die auswählen
Häkchen bei
- Basics
- Misc → Dirty Stacks
- Networking (da dein Programm ja offensichtlich Netzwerkfunktionalität nutzt)
nun dein Programm im Debugger laufen lassen
im Output-Fenster sollte eine der ersten Meldungen (zwischen Dutzenden foo.dll loaded) sowas sein wie AV Debug Heap enabled; daran siehst du, dass der Verifier mitläuft
- für dein Programm werden Allokationen nun so geändert, dass out-of-bounds-Zugriffe sofort im Debugger landen
- uninitialisierte Variablen kriegen jetzt hässliche Default-Werte, damit sie schnell auffallen
- viele WinAPI-Aufrufe werden auf Konsistenz überprüft
- falls du Multi-Threading nutzt, kannst du Cuzz aktivieren, was dein Programm sehr viel langsamer macht, aber das Timing der Threads möglichst stark stört damit mögliche Race Conditions und Deadlocks zu Tage treten
Re: [C++] WinApi: ClassName (?)
Okay, werd ich bei gelegenheit mal ausprobieren. Danke...