Mein erstes Fenster



  • Hallo, lerne gerade an Hand eines Buches C++ und hab gerade
    das Kapitel "Grundlagen Windows Programmierung" aufgeschlagen.
    Hier gleich zu Beginn ein Beispiel für ein schlichtes Windows
    Fenster.
    Leider funktioniert es so nicht, wie es im Buch steht. Kann mir
    da wer weiterhelfen?

    //C++ für Spieleprogrammierer
    //Listing 10.1
    //Ein Windows-Grundgerüst
    //
    #include <Windows.h>
    
    //Prototyp der Callback-Funktion
    LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    
    //Hauptprogramm
    //
    int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpcmdline, int ncmdshow)
    {
    	WNDCLASSEX	windowclass;	//Struktur für Fenstereigenschaften
    	HWND		hWnd;			//Fenster-Handle
    	MSG			message;		//Nachricht
    
    	//Der Klassen-Name des Fensters ist frei wählbar
    	const char szClassName[] = "Erstes Fenster";
    
    	//Struktur mit gewünschten Eigenschaften füllen
    	//
    
    	//Größe der Struktur zwischenspeichern
    	windowclass.cbSize = sizeof (WNDCLASSEX);
    
    	//Fenster soll beim Verschieben neu gezeichnet werden
    	windowclass.style = CS_HREDRAW | CS_VREDRAW;
    
    	//Zeiger auf Callback-Funktion
    	windowclass.lpfnWndProc = WindowProc;
    
    	//Keine erweiterten Einstellungen
    	windowclass.cbClsExtra = 0;
    	windowclass.cbWndExtra = 0;
    
    	//Instanz speichern
    	windowclass.hInstance = hInst;
    
    	//Icons und Cursor festlegen
    	windowclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    	windowclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    	windowclass.hCursor = LoadCursor (NULL, IDC_ARROW);
    
    	//Hintergrundfarbe festlegen
    	windowclass.hbrBackground = (HBRUSH) COLOR_BACKGROUND+1;
    
    	//Ein Menü brauchen wir nicht
    	windowclass.lpszMenuName = NULL;
    
    	//Fensterklasse regestrieren
    	if (!RegisterClassEx (&windowclass) )
    		return (0);
    
    	//Das Fenster erzeugen
    	hWnd = CreateWindowEx	(NULL,
    							szClassName,
    							"Das erste Fenster!",
    							WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    							100, 100, 
    							300, 250,
    							NULL,
    							NULL,
    							hInst,
    							NULL);
    
    	//Prüfen ob alles glatt ging
    	if (hWnd == NULL)
    		return (0);
    
    	//Der "Herzschlag des Programms.
    	//Hier werden alle Nachrichten abgeholt,
    	//übersetzt und weitergeleitet.
    	while (GetMessage (&message, NULL, 0, 0) )
    	{
    		TranslateMessage (&message);
    		DispatchMessage (&message);
    
    	}
    
    	//Programm beenden
    	return (int) (message.wParam);
    
    }//WinMain
    
    //Callback-Funktion zur Nachrichtenverarbeitung
    //
    LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	//Messages auswerten
    	switch (message)
    	{
    		//Fenster schließen? (auch alt +F4)
    		case WM_DESTROY:
    			{
    				//Nachricht zum Beenden schicken
    				PostQuitMessage (0);
    				return (0);
    
    			}
    
    			//Wurde eine Taste gedrückt?
    		case WM_KEYDOWN:
    			{
    				//Ja, also je nach Taste verzweigen
    				switch (wParam)
    				{
    					//Wurde "Escape" gedrückt?
    				case VK_ESCAPE:
    					{
    						//Ja, also Nachricht zum Beenden schicken
    						PostQuitMessage (0);
    						return (0);
    
    					}
    				}
    			} break;
    	}
    
    	//Die Nachricht wurde nicht von uns verarbeitet, also 
    	//von Windows verarbeiten lassen.
    	return (DefWindowProc (hWnd, message, wParam, lParam) );
    
    } //WindowProc
    

    Fehlermeldung:
    1>c:\users\lybrial\documents\visual studio 2010\projects\grundlagen windows programmierung\grundlagen windows programmierung\ein erstes fenster.cpp(65): error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'const char [15]' to 'LPCWSTR'
    1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast



  • entweder:

    L"Das erste Fenster!"
    

    oder in den Projektoptionen den Zeichensatz umstellen.



  • Dann sieht die Fehlermeldung so aus:

    1>c:\users\lybrial\documents\visual studio 2010\projects\grundlagen windows programmierung\grundlagen windows programmierung\ein erstes fenster.cpp(19): error C2440: 'initializing' : cannot convert from 'const wchar_t [15]' to 'const char []'
    1> There is no context in which this conversion is possible
    1>c:\users\lybrial\documents\visual studio 2010\projects\grundlagen windows programmierung\grundlagen windows programmierung\ein erstes fenster.cpp(65): error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'const char []' to 'LPCWSTR'
    1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

    Wie schon gesagt, das ist eine Copy aus einem Buch, kann mir eigentlich
    nicht vorstellen, dass die da so nen gravierenden Fehler machen.



  • Also EINE dieser Änderungen musst du vornehmen:

    char szClassName[] = "Erstes Fenster";
    
    hWnd = CreateWindowEx    (NULL,
                                (char*)szClassName,
                                "Das erste Fenster!",
                                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                                100, 100,
                                300, 250,
                                NULL,
                                NULL,
                                hInst,
                                NULL);
    

    Zur Erklärung:
    Er erwartet einen LPSCTR (LP = pointer - CSTR = Char-String, also ein char Array (char[]), also einen Pointer auf ein Char-array, du gibt ihm aber einen const char-array, welches (für) ihn ein Unterschied ist.
    Für dich heiß es nur, dass du etweder keinen const String verwenden darfst (Bsp. 1) oder ihm sagen musst, dass er es wie einen "normalen" String behandeln soll (char)stClassName)*.



  • Fehlermeldung bei Verwendung von Beispiel 1:

    1>c:\users\lybrial\documents\visual studio 2010\projects\grundlagen windows programmierung\grundlagen windows programmierung\ein erstes fenster.cpp(65): error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'char [15]' to 'LPCWSTR'
    1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

    Fehlermeldung bei Verwendung von Beispiel 2:

    1>c:\users\lybrial\documents\visual studio 2010\projects\grundlagen windows programmierung\grundlagen windows programmierung\ein erstes fenster.cpp(65): error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'char *' to 'LPCWSTR'
    1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast



  • Der Fehler hat nichts mit Const oder nicht Const zu tun.
    Wie unicode schon sagte, es liegt ein Problem mit dem Zeichensatz vor.
    Du könntest anstatt CreateWindowEx die ASCII-Version CreateWindowExA aufrufen.
    besser ist es aber, in den Projekt-Einstellungen den Zeichensatz von Unicode auf ASCII umzustellen.

    Eine weitere Möglichkeit wäre das mit dem L vor dem String:

    hWnd = CreateWindowEx    (NULL,
                                L"Erstes Fenster"
                                L"Das erste Fenster!",
                                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                                100, 100,
                                300, 250,
                                NULL,
                                NULL,
                                hInst,
                                NULL);
    

    MfG, Jochen



  • Jetzt hat sich was verändert.

    1> Ein erstes Fenster.cpp
    1> Grundlagen Windows Programmierung.vcxproj -> c:\users\lybrial\documents\visual studio 2010\Projects\Grundlagen Windows Programmierung\Debug\Grundlagen Windows Programmierung.exe
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

    Allerdings wird mir das Fenster nicht angezeigt 😞



  • Ruf mal vor der Nachrichtenschleife UpdateWindow und ShowWindow auf.
    also in Zeile 70 noch folgendes einfügen:

    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);
    

    So müsste das Fenster auch erscheinen.
    Anstatt SW_SHOW kannst du der Funktion auch den 4. Parameter der WinMain (in diesem Falle also ncmdshow übergeben.

    MfG, Jochen



  • Hmmm, nein sehe das Fenster leider trotzdem nicht 😞



  • ShowWindow braucht er nicht, aber das hier fehlt:

    windowclass.lpszClassName = szClassName;
    


  • Leider nicht, dann bekomme ich wieder die alte Fehlermeldung rein 😞



  • 🙂 Dann nicht "string", sondern TEXT("string"), und nicht char, sondern TCHAR:

    //nicht: char szClassName[] = "Erstes Fenster";
    TCHAR szClassName[] = TEXT("Erstes Fenster"); // ja!
    
    // CreateWindowEx
    TEXT("Das erste Fenster!")
    


  • So hats funktioniert Danke ! 😃
    Kannst du mir sagen was dahinter steckt?
    Also wieso es ein Text-string sein muss?



  • Eine Zeichenkette vom TCHAR stellt sich projektabhängig automatisch entweder auf char oder auf wchar, je nachdem ob UNICODE aktiv ist oder nicht.

    Das Makro TEXT(""), oder auch _T("") sorgen dafür das der ansonsten typenlose Text in den zum Projekt passenden Datentyp gespeichert wird.

    Will man sich die Arbeit erleichtern ist es empfehlenswert Zeichenketten immer objektbasiert abzulegen. Das ist insbesondere deshalb von Vorteil wenn man die Zeichenkette in verschiedenen Versionen benötigt. Ausserdem kümmert sich das Objekt selbst um den benötigten Speicher und gibt ihn auch automatisch wieder frei.

    Ich empfehle CString-Objekte.

    #include <atlstr.h> 
    
    using namespace std;
    

    Beispiele:

    CString str1;
    CString str2("hallo);
    
    str1 = str2 + TEXT(" super");
    
    wcout << str1.GetString() << endl;
    

Anmelden zum Antworten