2 Probleme



  • Da mein alter Thread anscheinend gelöscht wurde, mach ich jetzt mal einen neuen auf.
    Also momentan habe ich jetzt eine Fensterklasse, die fürs erste so aussieht:

    class Application {
    public:
    	HINSTANCE			hInstance;						// Application Instance
    	LPWSTR				className;						// Application ClassName
    };
    
    class WindowInitGL {
    public:
    	Application			application;					// Application Klasse
    	wchar_t				title[100];						// Window Title
    	int					width;							// Width
    	int					height;							// Height
    	int					bpp;							// Bits Per Pixel
    	bool				fullscreen;						// fullscreen flag
    };
    
    class WindowGL {
    public:
    	//Keys				keys;							// Tasten aktionen
    	bool				keyDown [256];					// Speichert true/false für jede Taste
    	HWND				hWnd;							// Fenster Handle
    	HDC					hDC;							// Device Context
    	HGLRC				hRC;							// Rendering Context
    	WindowInitGL		init;							// Fenster Initialisierung
    	bool				visible;						// Fenster sichtbar?
    	bool				active;							// Ist Fenster aktiv?
    	bool				readSettings(void);				// Settings lesen und Speichern
    	bool				LoadTexturesGL(void);			// Texturen laden
    	bool				CreateWindowGL(void);			// Fenster erzeugen
    	GLvoid				KillWindowGL(GLvoid);			// Fenster zerstören
    	bool				InitGL(GLvoid);					// Fenster Initialisieren
    	GLvoid				ReshapeGL(GLsizei width, GLsizei height);
    	GLvoid				DrawGL(GLvoid);					// Fenster zeichnen
    	int					TranslateMsg(UINT msg, LPARAM lParam, WPARAM wParam); // System Msg verarbeiten
    	bool				ProgramIsLooping(void);			// Programm läuft noch
    	void				TerminateApplication(void);		// Application beenden
    private:
    	bool programloop;
    };
    

    Dann erstelle ich mit

    WindiwGL* mainwindow = new WindowGL;
    

    eine Instanz und möchte sie so löschen:

    delete Mainwindow;
    

    Das ganze funktioniert zwar, und der Debugger meckert nicht, aber immer wenn ich das Programm schließe, also die Klasseninstanz gelöscht wird ertönt der Windows XP Fehlerton bei mir. Aber das wars eigentlich auch an Fehler die auftreten.
    Jetzt möchte ich natürlich nicht, dass immer ein Fehlerton kommt. Kann mir da wer weiterhelfen?

    Und dann habe ich noch eine zweite Frage. Bisher habe ich die Systemnachrichten immer ganz normal im Code bearbeitet. Jetzt wollte ich dafür in der WindowGL Class eine Funktion schreiben, die ich dann so aufrufe:

    mainwindow->TranslateMsg(uMsg, lParam, wParam);
    

    Die Funktion TranslateMsg sieht dann so aus:

    int WindowGL::TranslateMsg(UINT msg, LPARAM lParam, WPARAM wParam) {
    	switch (msg) {														// Überprüfe auf Fensternachrichten
    
    		case WM_CREATE:													// Fenster wird erstellet
    		{
    			CREATESTRUCT* creation = reinterpret_cast<CREATESTRUCT*>(lParam);
    			this = reinterpret_cast<WindowGL*>(creation->lpCreateParams);
    			SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast<long>(this));
    		}
    		return 0;
    
    		case WM_ACTIVATE: 												// Wenn Aktivierungs-Nachricht reinkommt
    			if (!HIWORD(wParam)) {										// Überprüfe Minimierungs-Status
    				active = true;											// Programm ist aktiv
    			} else { 
    				active = false;											// Programm ist nicht länger aktiv
    			}
    		return 0;														// Kehre zurück zur Nachrichten-Schleife
    
    		case WM_SYSCOMMAND:
    			switch (wParam) {
    				case SC_SCREENSAVE:										// versucht der Screensaver sich zu starten?
    				case SC_MONITORPOWER:									// versucht der Monitor in den Energiesparmodus zu gehen?
    				return 0;												// verhindere das
    			}
    		break;
    
    		case WM_CLOSE:
    			PostMessage(hWnd, 0, 0, 0);
    			TerminateApplication();										// Sende eine Beenden-Nachricht
    		return 0;
    
    		case WM_KEYDOWN:												// Taste wurde gedrückt
    			if ((wParam >= 0) && (wParam <= 255)) {						// Ist wParam gültig
    				keyDown[wParam] = true;									// gedrückte Taste ist true
    				return 0;
    			}
    		break;
    
    		case WM_KEYUP:													// Taste wurde losgelassen
    			if ((wParam >= 0) && (wParam <= 255)) {						// Ist wParam gültug
    				keyDown[wParam] = false;								// gedrückte Taste ist false
    				return 0;
    			}
    		break;
    
    		case WM_SIZE:													// Size Message
    			switch (wParam)												// Evaluate Size Action
    			{
    				case SIZE_MINIMIZED:									// Fenster wurde minimiert
    					visible = false;									// visible ist flase
    				return 0;
    
    				case SIZE_MAXIMIZED:									// Fenster wurde maximiert
    					visible = true;										// visible ist true
    					ReshapeGL(LOWORD (lParam), HIWORD (lParam));		// Reshape Window - LoWord = Width, HiWord = Height
    				return 0;
    			}
    		break;
    	}
    };
    

    Jetzt weiß ich, dass bei WM_CREATE "this" kein L-Wert ist, und da liegt auch das Problem. Denn bisher habe ich die Nachrichten so abgearbeitet:

    switch (uMsg) {														// Überprüfe auf Fensternachrichten
    
    		case WM_CREATE:													// Fenster wird erstellet
    		{
    			CREATESTRUCT* creation = reinterpret_cast<CREATESTRUCT*>(lParam);
    			mainwindow = reinterpret_cast<WindowGL*>(creation->lpCreateParams);
    			SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast<long>(mainwindow));
    		}
    		return 0;
    
    		case WM_ACTIVATE: 												// Wenn Aktivierungs-Nachricht reinkommt
    			if (!HIWORD(wParam)) {										// Überprüfe Minimierungs-Status
    				mainwindow->active = true;								// Programm ist aktiv
    			} else { 
    				mainwindow->active = false;								// Programm ist nicht länger aktiv
    			}
    		return 0;														// Kehre zurück zur Nachrichten-Schleife
    
    		case WM_SYSCOMMAND:
    			switch (wParam) {
    				case SC_SCREENSAVE:										// versucht der Screensaver sich zu starten?
    				case SC_MONITORPOWER:									// versucht der Monitor in den Energiesparmodus zu gehen?
    				return 0;												// verhindere das
    			}
    		break;
    
    		case WM_CLOSE:
    			mainwindow->TerminateApplication();							// Sende eine Beenden-Nachricht
    		return 0;
    
    		case WM_KEYDOWN:												// Taste wurde gedrückt
    			if ((wParam >= 0) && (wParam <= 255)) {						// Ist wParam gültig
    				mainwindow->keys.keyDown[wParam] = true;				// gedrückte Taste ist true
    				return 0;
    			}
    		break;
    
    		case WM_KEYUP:													// Taste wurde losgelassen
    			if ((wParam >= 0) && (wParam <= 255)) {						// Ist wParam gültug
    				mainwindow->keys.keyDown[wParam] = false;				// gedrückte Taste ist false
    				return 0;
    			}
    		break;
    
    		case WM_SIZE:													// Size Message
    			switch (wParam)												// Evaluate Size Action
    			{
    				case SIZE_MINIMIZED:									// Fenster wurde minimiert
    					mainwindow->visible = false;						// visible ist flase
    				return 0;
    
    				case SIZE_MAXIMIZED:									// Fenster wurde maximiert
    					mainwindow->visible = true;							// visible ist true
    					mainwindow->ReshapeGL(LOWORD (lParam), HIWORD (lParam));	// Reshape Window - LoWord = Width, HiWord = Height
    				return 0;
    			}
    		break;
    }
    

    Wie kann ich es jetzt realiesen, dass TranslateMsg() auch das Fenster korrekt erzeugt. An WM_CREATE wird ein this von WindowGL weitergegeben.

    Danke schonmal für eure Hilfe.



  • Das gehört ins WinAPI Forum.



  • Zur ersten Frage:
    Zeig mal bitte deine CreateWindowGL, InitGL und KillWindowGL Implementierung.
    So kann man da schlecht den Fehler finden.

    Zur zweiten Frage.
    Das mit dem this = ... geht natürlich nicht.
    Da kannst du nur jeden member einzeln zuweisen, bzw. das ganze in eine Init-Methode kapseln.

    Den reinterpret_cast find ich übrigens sehr brutal. Geht das nicht auch anders? Hab zwar weniger Ahnung von der Windows API aber, sind diese Messages dafür da um ganze Objekte mit zu übergeben?



  • Naja der Thread gehört halb ins WinApi Forum 😉
    Sollen die Moderatoren entscheiden, wo er hingehört.

    Zum ersten Problem:
    Ich habe mal die komplette WindowGL.cpp bei pastebin gepostet. Die Position der Kommentare ist zwar ziemlich verhunzt, aber ganz weglassen wollte ich sie jetzt auch nicht.
    http://pastebin.com/mgf41EfB

    Zum zweiten Problem:
    Ich finde die reinterpret_casts auch sehr brutal, aber so hat es funktioniert.
    Ich habe die Methode aus dem NeHe Tutorial, allerdings hätte ich nichts dagegen, das Fenster irgendwie anders zu erstellen, hauptsache es funktioniert. Wenn da jemand ein paar Tipps hätte, wäre ich sehr dankbar.



  • Kommt dein seltsamer Ton beim delete (Aufruf Destructor den du ja nicht definiert hast) oder beim KillWindowGL? Kannst das doch einfach mal durchdebuggen um die genaue Stelle zu finden. Hast du das schonmal gemacht?



  • Das ich den Ton nicht schon vorher gehört habe, lag anscheinend daran, dass ich meine Boxen nie an hatte. Ich habe gerade nochmal nachgeschaut und den Ton erzuegen diese beiden MessageBoxen, die sofort wieder verschwinden:

    if (hDC && !ReleaseDC(hWnd,hDC)) {									// Können wir DC freigeben?
    		MessageBox(NULL, _T("Freigabe des Device Kontext gescheitert."), _T("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
    		hDC = NULL;														// Setze DC auf NULL
    	}
    
    	if (hWnd && !DestroyWindow(hWnd)) {									// Können wir das Fenster zerstören?
    		MessageBox(NULL, _T("Zerstören des Fenster-Handle gescheitert."), _T("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
    		hWnd = NULL;													// Setze hWnd auf NULL
    	}
    

    Also der Device Kontext und der Fenster Handle können nicht freigegeben werden.
    Und da habe ich direkt noch eine Frage: Wie schaffe ich es, dass die MessageBox solange da bleibt, bis ich OK gedrückt habe?
    Mit if(MessageBox(....) == IDOK) klappt es nicht.



  • So, ich habe jetzt nochmal ein bisschen in der MSDN rumgestöbert, und dann GetLastError() ausprobiert. Das ist anscheinend die einzige Möglichkeit, irgendwas herauszufinden. Aber GetLastError() gibt immer den Wert 3435973836 zurück. Und damit kann man wenig anstellen.
    Falls es noch relevant ist: Der Wert "unused" von hWnd ändert sich immer im Laufe des Programms. Aber Google sagt, der Wert ist irrelevant.



  • Warum gehen die MessageBoxen sofort wieder zu?
    Warum musst du gleich eine MessageBox öffnen?
    Was genau scheitert denn, so dass die If-Bedingungen erfüllt sind.
    Normalerweise müsste das ja klappen. Ist HDC richtig initialisiert wurden bevor du es zerstörst?
    Liegt es an ReleaseDC oder DestroyWindow?
    Hast du vor dem ReleaseDC die Funktionen GetWindowDC oder GetDC aufgerufen?
    Welche Zahl gibt ReleaceDC zurück?
    Wenn du das DC mit CreateDC erzeugt hast darfst du es nicht mit ReleaseDC freigeben, sondern musst DeleteDC verwenden.
    Außerdem muss ReleaseDC im selben Thread aufgerufen werden, in dem auch GetDC aufgerufen wurde. Das selbe gilt für CreateWindow und DestroyWindow.

    Das würde ich jetzt erstmal versuchen rauszufinden.



  • Und debugge das nochmal durch und guck mal wann die Box aufgeht und wieder zu.
    Ich vermute, dass ein anderer Thread dein Hauptfenster zerstört und dadurch die MessageBox keinen Owner mehr hat. Setze entweder mal den ersten Parameter auf hWnd oder versuchs mal mit dem zusätzlichem Style MB_TASKMODAL oder MB_SYSTEMMODAL.



  • Sehen tut man die MessageBox garnicht. Wenn man bis zur Zeiler der MB debuggt, erscheint noch nichts, und wenn man bis zur Zeile danach debuggt hört man nur den Ton. Als ersten Parameter hWnd zu benutzen erscheint mir sinnlos, da ja genau dieser zerstört werden soll. MB_TASKMODAL oder MB_SYSTEMMODAL haben auch keinen Effekt, dass die MB's länger offen bleiben.



  • Kann ein Moderator den Thread mal ins WinApi Forum verschieben?
    Wäre nett 🙂



  • Dieser Thread wurde von Moderator/in volkard aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • So, ich habe jetzt noch bemerkt, dass wen ich die ganzen Nachrichten normal abarbeite, ohne Funktion, wie ich es eine seite vorher schon gepostet habe, funktioniert alles einwandfrei.
    Allerdings war mein Ziel genau der gegenteil. Und zwar, dass ich mit der Funktion TranslateMsg alle Nachrichten korrekt abarbeiten kann. Auch WM_CREATE. Kann mir da jemand ein paar Tipps geben? 🙂


Anmelden zum Antworten